我是C ++(在Windows上)和线程的新手,我正在尝试使用互斥锁,信号量和事件找到解决问题的方法。 我正在尝试使用构造函数和名为Enter的方法创建一个Barrier类。具有唯一方法Enter的Barrier类应该阻止任何进入它的线程,直到许多线程已经到达该方法。在构造函数中收到的等待它的线程数。 我的问题是如何使用锁来创建该效果?我需要的是像反向信号量一样的东西,它保持线程直到达到计数,而不是像常规信号量工作那样让线程进入到计数之前。 关于如何解决这个问题的任何想法都会很棒。 谢谢, Netanel。
答案 0 :(得分:1)
也许:
在ctor中,存储限制计数并创建一个空信号量。
当一个线程调用Enter时,首先锁定一个互斥锁,这样你就可以安全地旋转内部。将线程数计入限制计数。如果尚未达到限制,请释放互斥锁并等待信号量。如果达到限制,则在循环中发出信号量[limit-1]次信号,将线程数归零(准备下次),释放互斥锁并从Enter()返回。正在等待信号量并且现在准备好/正在运行的任何线程都应该从他们的“Enter”调用返回。
互斥锁防止任何已释放的线程从“再次进入”循环,直到所有调用“Enter”并等待的线程都已设置为运行并且屏障被重置。
答案 1 :(得分:1)
您可以使用条件变量实现它。
以下是一个例子:
我声明了25个线程并使用WorkerThread函数启动它们。
我正在检查阻止/取消单击线程的条件是该部分中的线程数是否小于2。 (我添加了一些断言来证明我的coode做了什么)。
我的代码只是在关键部分休眠,之后我减少了关键部分中的线程数。
我还为cout添加了一个互斥锁,以获得干净的消息。 #包括 #包括 #包括 #包括 #包括 #包括 #include / *断言* / 使用namespace std;
std::mutex m;
atomic<int> NumThreadsInCritialSection=0;
int MaxNumberThreadsInSection=2;
std::condition_variable cv;
mutex coutMutex;
int WorkerThread()
{
// Wait until main() sends data
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return NumThreadsInCritialSection<MaxNumberThreadsInSection;});
}
assert (NumThreadsInCritialSection<MaxNumberThreadsInSection);
assert (NumThreadsInCritialSection>=0);
NumThreadsInCritialSection++;
{
std::unique_lock<std::mutex> lk(coutMutex);
cout<<"NumThreadsInCritialSection= "<<NumThreadsInCritialSection<<endl;
}
std::this_thread::sleep_for(std::chrono::seconds(5));
NumThreadsInCritialSection--;
{
std::unique_lock<std::mutex> lk(coutMutex);
cout<<"NumThreadsInCritialSection= "<<NumThreadsInCritialSection<<endl;
}
cv.notify_one();
return 0;
}
int main()
{
vector<thread> vWorkers;
for (int i=0;i<25;++i)
{
vWorkers.push_back(thread(WorkerThread));
}
for (auto j=vWorkers.begin(); j!=vWorkers.end(); ++j)
{
j->join();
}
return 0;
}
希望有所帮助,告诉我您是否有任何问题,我可以发表评论或更改我的代码。
答案 2 :(得分:0)
伪代码轮廓可能如下所示:
void Enter()
{
Increment counter (atomically or with mutex)
if(counter >= desired_count)
{
condition_met = true; (protected if bool writes aren't atomic on your architecture)
cond_broadcast(blocking_cond_var);
}
else
{
Do a normal cond_wait loop-plus-predicate-check (waiting for the broadcast and checking condition_met each iteration to protect for spurious wakeups).
}
}