Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 带有信号量的线程安全单例问题_C++_Multithreading_Semaphore - Fatal编程技术网

C++ 带有信号量的线程安全单例问题

C++ 带有信号量的线程安全单例问题,c++,multithreading,semaphore,C++,Multithreading,Semaphore,我已经编写了一个简单的单例应用程序 下面是我的示例主类 // ThreadsafeSingletonUsingSemaphore.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <iostream> #include <conio.h> #include "MySingleton.h" using namespace std; int

我已经编写了一个简单的单例应用程序

下面是我的示例主类

// ThreadsafeSingletonUsingSemaphore.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include "MySingleton.h"
using namespace std;

int i =0;
#define THREADCOUNT 100
DWORD WINAPI ThreadProc(LPVOID lParam);
HANDLE g_semaphore = NULL;

int _tmain(int argc, _TCHAR* argv[])
{
    g_semaphore = CreateSemaphore(NULL,1,1,_T("TreadOne"));
    HANDLE hThread[THREADCOUNT];
    DWORD aThreadID;

    for(int iCount = 0; iCount < THREADCOUNT ; iCount++)
    {
        hThread[iCount] = CreateThread(NULL, 0, ThreadProc, 0,0, &aThreadID);
        if( hThread[iCount] == NULL )
        {
            cout<<"CreateThread error: %d" << GetLastError() << endl;
            return 1;
        }
    }

    WaitForMultipleObjects(THREADCOUNT, hThread, TRUE, INFINITE);

    // Close thread and semaphore handles
    for(int i=0; i < THREADCOUNT; i++ )
        CloseHandle(hThread[i]);

    cout << MySingleton::getInstance().getCounter() << endl ;

    CloseHandle(g_semaphore);
    _getch();
    return 0;
}

DWORD WINAPI ThreadProc(LPVOID lpParam)
{
    //DWORD result = WaitForSingleObject(g_semaphore,INFINITE);
    //if(WAIT_OBJECT_0 == result)
        MySingleton::getInstance().incrementCouner();
    //ReleaseSemaphore(g_semaphore,1, NULL);
    return TRUE;
}
//ThreadsafeSingletonUsingSemaphore.cpp:定义控制台应用程序的入口点。
//
#包括“stdafx.h”
#包括
#包括
#包括“MySingleton.h”
使用名称空间std;
int i=0;
#定义THREADCOUNT 100
DWORD WINAPI ThreadProc(LPVOID LPRAM);
句柄g_信号量=NULL;
int _tmain(int argc,_TCHAR*argv[]
{
g_semaphore=CreateSemaphore(NULL,1,1,_T(“TreadOne”);
句柄hThread[THREADCOUNT];
德沃德·阿瑟雷迪德;
对于(int-iCount=0;iCountcout您不需要编写所有这些代码。实现线程安全单例的最简单方法是使用Scott Meyer的单例习惯用法:

class Singleton {
    int counter;
    mutable std::mutex counter_guard;
    Singleton() {}
public:
    Singleton(const Singleton&) = delete;
    Singleton(Singleton&&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    Singleton& operator=(Singleton&&) = delete;

    static Singleton& instance() {
        static Singleton theInstance;
        return theInstance;
    }

    void setCounter(int newVal) {
        std::unique_lock<std::mutex> lock(counter_guard);
        counter = newVal;
    }  
    void incrementCounter() {
        std::unique_lock<std::mutex> lock(counter_guard);
        ++counter;
    }  
    int getCounter() const {
        std::unique_lock<std::mutex> lock(counter_guard);
        return counter;
    }  
};
类单例{
整数计数器;
可变std::互斥计数器\u保护;
Singleton(){}
公众:
单例(const Singleton&)=删除;
单例(单例&&)=删除;
单例&运算符=(常量单例&)=delete;
单例&运算符=(单例&&)=删除;
静态单例和实例(){
静态单态介子;
返回指令;
}
无效设置计数器(int newVal){
标准::独特的锁(计数器保护);
计数器=newVal;
}  
void incrementCounter(){
标准::独特的锁(计数器保护);
++计数器;
}  
int getCounter()常量{
标准::独特的锁(计数器保护);
返回计数器;
}  
};


更简单的方法是为
计数器
成员变量使用一个类型。然后可以完全忽略互斥锁和锁保护。

问题是对
WaitForMultipleObjects
的调用最多可以处理
最大等待对象,至少在Visual Studio 2017中是64个

请注意,调用
WaitForMultipleObjects
加入线程如何返回
WAIT\u失败

为了等待更多的对象,应该:

要等待多个最大\u wait\u对象句柄,请使用以下方法之一:

  • 创建一个线程以等待最大\u wait\u对象句柄,然后等待该线程和其他句柄。使用此技术将句柄拆分为最大\u wait\u对象组
  • 调用RegisterWaitForSingleObject以等待每个句柄。线程池中的等待线程等待已注册对象的最大等待时间,并在对象发出信号或超时间隔过期后分配工作线程

为什么不使用C++自己的线程功能,而不是Win32?@prv不编辑带答案的问题。在答案中发布更正的代码,而不是在问题上。如果有人解决了你的问题,请向上投票,并给他们打勾,如果他们帮助向上投票。允许自我回答;编辑问题使现有答案毫无意义。我相信我写单例是这个练习的一部分。谢谢你的回答。问题不在于单例。问题在于我在单例中的计数器。我希望在程序执行结束时,计数器值将与主线程计数相同,但不是。这是我无法理解的。@PrV,我更想回答您在问题标题中的问题。无论如何,我展示的代码是实现(线程安全)的惯用方法Singleton在C++中。对不起,我只是在学习。我知道我的代码可能是愚蠢的。我真的不理解这个线程安全的事情。再次抱歉。@ USER442,OP的SUNITLON确实包含一些数据,而您的数据不这样。您的线程对于单体创建是安全的,但如果包含任何数据,则不会是这样。需要访问后创建,这是我见过的每个单身汉都需要做的。你完全正确。非常感谢现在我明白了问题所在。再次非常感谢
#pragma once
#include <windows.h>
#include <iostream>
#include <conio.h>
using namespace std;

class MySingleton
{
private:
    static HANDLE m_hSem, m_One;
    HANDLE m_hCountSem;
    static MySingleton* m_instance;
    int m_counter;
    MySingleton();
    MySingleton(const MySingleton& obj_in);
    MySingleton& operator=(const MySingleton& obj_in);
public:
    ~MySingleton(void);

    static MySingleton& getInstance();
    void setCouner(int iCount_in);
    int getCounter();

    void incrementCouner();
};
class Singleton {
    int counter;
    mutable std::mutex counter_guard;
    Singleton() {}
public:
    Singleton(const Singleton&) = delete;
    Singleton(Singleton&&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    Singleton& operator=(Singleton&&) = delete;

    static Singleton& instance() {
        static Singleton theInstance;
        return theInstance;
    }

    void setCounter(int newVal) {
        std::unique_lock<std::mutex> lock(counter_guard);
        counter = newVal;
    }  
    void incrementCounter() {
        std::unique_lock<std::mutex> lock(counter_guard);
        ++counter;
    }  
    int getCounter() const {
        std::unique_lock<std::mutex> lock(counter_guard);
        return counter;
    }  
};