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—很难出错。