我知道我可以使用条件变量来同步线程之间的工作,但是有任何类like this (condition variable)
来同步进程之间的工作,提前感谢
答案 0 :(得分:2)
您可以使用named semaphore或named mutex。您还可以通过shared memory在进程之间共享内存。
答案 1 :(得分:1)
使用一对名为Semaphore
的对象,一个用于发信号,一个用作锁。 Windows上的命名同步对象是自动进行处理的,它会为您处理该部分工作。
这样的一个类就可以了。
class InterprocessCondVar {
private:
HANDLE mSem; // Used to signal waiters
HANDLE mLock; // Semaphore used as inter-process lock
int mWaiters; // # current waiters
protected:
public:
InterprocessCondVar(std::string name)
: mWaiters(0), mLock(NULL), mSem(NULL)
{
// NOTE: You'll need a real "security attributes" pointer
// for child processes to see the semaphore!
// "CreateSemaphore" will do nothing but give you the handle if
// the semaphore already exists.
mSem = CreateSemaphore( NULL, 0, std::numeric_limits<LONG>::max(), name.c_str());
std::string lockName = name + "_Lock";
mLock = CreateSemaphore( NULL, 0, 1, lockName.c_str());
if(!mSem || !mLock) {
throw std::runtime_exception("Semaphore create failed");
}
}
virtual ~InterprocessCondVar() {
CloseHandle( mSem);
CloseHandle( mLock);
}
bool Signal();
bool Broadcast();
bool Wait(unsigned int waitTimeMs = INFINITE);
}
真正的条件变量提供3个电话:
1)“信号()”:唤醒一个等待线程
bool InterprocessCondVar::Signal() {
WaitForSingleObject( mLock, INFINITE); // Lock
mWaiters--; // Lower wait count
bool result = ReleaseSemaphore( mSem, 1, NULL); // Signal 1 waiter
ReleaseSemaphore( mLock, 1, NULL); // Unlock
return result;
}
2)“Broadcast()”:唤醒所有线程
bool InterprocessCondVar::Broadcast() {
WaitForSingleObject( mLock, INFINITE); // Lock
bool result = ReleaseSemaphore( mSem, nWaiters, NULL); // Signal all
mWaiters = 0; // All waiters clear;
ReleaseSemaphore( mLock, 1, NULL); // Unlock
return result;
}
3)“等待()”:等待信号
bool InterprocessCondVar::Wait(unsigned int waitTimeMs) {
WaitForSingleObject( mLock, INFINITE); // Lock
mWaiters++; // Add to wait count
ReleaseSemaphore( mLock, 1, NULL); // Unlock
// This must be outside the lock
return (WaitForSingleObject( mSem, waitTimeMs) == WAIT_OBJECT_0);
}
这应确保Broadcast()仅唤醒线程&amp;已经在等待的流程,而不是所有未来的流程。这也是一个非常重量级的对象。对于不需要跨进程存在的CondVar,我将创建一个具有相同API的不同类,并使用未命名的对象。
答案 2 :(得分:1)
对于我正在进行的项目,我需要一个条件变量和互斥实现,它可以处理死进程并且不会导致其他进程在这种情况下陷入死锁。我使用WIN32 api提供的本机命名互斥锁实现了互斥锁,因为它们可以通过返回WAIT_ABANDONED来指示死进程是否拥有锁。下一个问题是我还需要一个条件变量,我可以跨进程使用这些互斥锁。我从user3726672的建议开始,但很快发现有几个问题,其中计数器变量的状态和信号量的状态最终都是无效的。
在做了一些研究之后,我发现了微软研究院的一篇论文,它正好解释了这个场景:Implementing Condition Variables with Semaphores。它为每个线程使用单独的信号量来解决上述问题。
我的最终实现使用了一部分共享内存,我在其中存储了一个thread-iid的ringbuffer(等待线程的id)。然后,进程为每个尚未遇到的命名信号量/ thread-id创建自己的句柄并缓存它。信号/广播/等待功能非常直接,并遵循本文提出的解决方案的想法。如果等待操作失败或导致超时,请记住从ringbuffer中删除你的thread-id。
对于Win32实现,我建议您阅读以下文档: Semaphore Objects和Using Mutex Objects正如那些描述了您实施所需的功能。
替代方案:boost :: interprocess具有一些强大的互斥模拟支持,但它基于自旋锁并在我们的嵌入式系统上造成了非常高的CPU负载,这是我们调查自己的实现的最终原因。
@ user3726672:您是否可以更新您的帖子以指向此帖子或引用的论文?
最诚挚的问候, 迈克尔
<强>更新强> 我还看了一下linux / posix的实现。原来pthread已经提供了你需要的一切。只需将pthread_cond_t和pthread_mutex_t放在某个共享内存中,与其他进程共享,并使用PTHREAD_PROCESS_SHARED进行初始化。还要在互斥锁上设置PTHREAD_MUTEX_ROBUST。
答案 3 :(得分:0)
是。您可以使用(命名)Mutex。使用CreateMutex
创建一个。然后等待它(使用WaitForSingleObject
等函数),并在完成ReleaseMutex
后释放它。
答案 4 :(得分:0)
作为参考,Boost.Interprocess(documentation for version 1.59)具有条件变量等等。但是,请注意,在撰写本文时,&#34; Win32 synchronization is too basic&#34;。