Winapi 在线程之间共享对象

Winapi 在线程之间共享对象,winapi,multithreading,Winapi,Multithreading,如何设置线程之间共享的对象数据,并且在繁忙循环中(比如)两个线程的完整循环后需要更新一次 CRITICAL_SECTION critical_section_; int value; //needs to be updated once after the cycle of any number of threads running in busy loop void ThreadsFunction(int i) { while (true) { EnterCriticalSect

如何设置线程之间共享的对象数据,并且在繁忙循环中(比如)两个线程的完整循环后需要更新一次

CRITICAL_SECTION critical_section_;

int value; //needs to be updated once after the cycle of any number of threads running in busy loop

void ThreadsFunction(int i)
{

 while (true)
 {
  EnterCriticalSection(&critical_section_);
                /* Lines of Code */
  LeaveCriticalSection(&critical_section_);
 }
}

编辑:值可以是任何类的对象。

如果要实现整数的线程安全更新,最好使用
联锁增量
联锁增量
联锁交换添加
函数。看

如果您确实需要使用
EnterCriticalSection
LeaveCriticalSection
,您将在中找到一个示例,但我建议您使用
EnterCriticalSection
中的
EnterCriticalSection
尝试
块和
LeaveCriticalSection
中的
最后
部分。两个建议:

  • 使对象本身线程安全
  • 将对象作为实例数据传递到线程中

我将用C++作为例子。如果需要,可以很容易地将其转换为纯C

//MyObject是要在线程之间共享的核心数据

struct MyObject
{
   int value;
   int othervalue;
   // all all the other members you want here
};


class MyThreadSafeObject
{
private:
    CRITICAL_SECTION _cs;
    MyObject _myojbect;
    bool _fLocked;
public:
    MyThreadSafeObject()
    {
        _fLocked = false
        InitializeCriticalSection();
    }
    ~MYThreadSafeObject()
    {
        DeleteCriticalSection();
    }

    // add "getter and setter" methods for each member in MyObject
    int SetValue(int x)
    {
         EnterCriticalSection(&_cs);
             _myobject.value = x;
         LeaveCriticalSection(&_cs);
    }

    int GetValue()
    {
         int x;
         EnterCriticalSection(&_cs);
             x = _myobject.value;
         LeaveCriticalSection(&_cs);
         return x;
    }

    // add "getter and setter" methods for each member in MyObject
    int SetOtherValue(int x)
    {
         EnterCriticalSection(&_cs);
             _myobject.othervalue = x;
         LeaveCriticalSection(&_cs);
    }

    int GetOtherValue()
    {
         int x;
         EnterCriticalSection(&_cs);
             x = _myobject.othervalue;
         LeaveCriticalSection(&_cs);
         return x;
    }


    // and if you need to access the whole object directly without using a critsec lock on each variable access, add lock/unlock methods
    bool Lock(MyObject** ppObject)
    {
        EnterCriticalSection(&_cs);
        *ppObject = &_myobject;
        _fLocked = true;
        return true;                
    }

    bool UnLock()
    {
        if (_fLocked == false)
            return false;

        _fLocked = false;
        LeaveCriticalSection();
        return true;
    }
};
然后,按如下方式创建对象和线程:

MyThreadSafeObject* pObjectThreadSafe;
MyObject* pObject = NULL;

// now initilaize your object
pObjectThreadSafe->Lock(&pObject);
   pObject->value = 0; // initailze value and all the other members of pObject to what you want them to be.
   pObject->othervalue = 0;
pObjectThreadSafe->Unlock();
pObject = NULL;


// Create your threads, passing the pointer to MyThreadSafeObject as your instance data
DWORD dwThreadID = 0;
HANDLE hThread = CreateThread(NULL, NULL, ThreadRoutine, pObjectThreadSafe, 0, &dwThreadID);


And your thread will operate as follows
DWORD __stdcall ThreadFunction(void* pData)
{
    MyThreadSafeObject* pObjectThreadSafe = (MyThreadSafeObject*)pData;
    MyObject* pObject = NULL;

    while (true)
    {
       /* lines of code */
           pObjectThreadSafe->SetValue(x);
       /* lines of code */         
    }

}

请注意,联锁功能很难正确实现。如果你所做的只是增加或减少一个变量,它们是相当安全的,但要正确使用它们却非常困难。说真的,我只知道MSFT有十几个我相信会写无锁代码的人(我不是其中之一)。只需进出关键区域,您会更安全。如果您发现由于上下文切换导致CPU使用过度,请使用自旋计数初始化critsec,这应该会有所帮助。@Larry。对不起,我不明白在使用互锁函数时有什么这么复杂。它们非常容易理解,并且在所有处理器体系结构中具有最好的性能。Oleg:我所知道的最好的例子是“双重检查锁模式”。从表面上看,DCLP是安全的,但正如本文所解释的,它实际上是一个破损的模式。Herb Sutter在这里引用了一篇关于并发性的专栏文章:一个缺点:您可能希望使用自动锁(参见ATL的CCritSecLock的示例),而不是显式的锁和释放API—很难出错。