C++ 可重用的简单(交替)实现 std::mutex mutex; std::条件变量cv; uint8_t尺寸=2; uint8\u t计数=大小; uint8_t方向=-1; 常量自动同步=[&size、&count、&mutex、&cv、&direction]()/。 { { std::唯一锁(互斥锁); 自动电流方向=方向; 如果(--count==0) { 计数=大小; 方向*=-1; cv.通知所有人(); } 其他的 { cv.等待(锁定, [&方向和当前方向]()/。 {返回方向!=当前_方向;}); } } };
如第一份不可接受的答复所述:C++ 可重用的简单(交替)实现 std::mutex mutex; std::条件变量cv; uint8_t尺寸=2; uint8\u t计数=大小; uint8_t方向=-1; 常量自动同步=[&size、&count、&mutex、&cv、&direction]()/。 { { std::唯一锁(互斥锁); 自动电流方向=方向; 如果(--count==0) { 计数=大小; 方向*=-1; cv.通知所有人(); } 其他的 { cv.等待(锁定, [&方向和当前方向]()/。 {返回方向!=当前_方向;}); } } };,c++,multithreading,c++11,barrier,C++,Multithreading,C++11,Barrier,如第一份不可接受的答复所述: “生成”必须存储在屏障对象中,以防止下一代为给定的线程集操纵当前生成的唤醒“条件”。我不喜欢第一个不被接受的答案是代数不断增长的计数器,我认为我们最多只需要区分两代,也就是说,如果一个线程满足了等待条件,并像第二个不被接受的解决方案所建议的那样启动了另一个屏障同步调用,然而,第二个解决方案有些复杂,我相信上面的代码片段就足够了(目前在main内部本地实现,但可以抽象为一个结构)。我认为屏障最多只能同时使用两代,这一“信念”正确吗?如果捕获点处的count为0,则确实
“生成”必须存储在屏障对象中,以防止下一代为给定的线程集操纵当前生成的唤醒“条件”。我不喜欢第一个不被接受的答案是代数不断增长的计数器,我认为我们最多只需要区分两代,也就是说,如果一个线程满足了等待条件,并像第二个不被接受的解决方案所建议的那样启动了另一个屏障同步调用,然而,第二个解决方案有些复杂,我相信上面的代码片段就足够了(目前在main内部本地实现,但可以抽象为一个结构)。我认为屏障最多只能同时使用两代,这一“信念”正确吗?如果捕获点处的
count
为0,则确实会发生不好的事情。你能详细说明一下吗?count目前仅公开,因为我使用lambda,我会将所有这些都更改为一个结构,该结构将大小作为一个成员函数的输入,没有任何参数。我不确定我是否理解这里的目标。在顶部,以下是可能的。线程1等待方向翻转。线程2翻转方向并通知所有线程。但是,在线程1有机会醒来并检查状态之前,其他线程调用sync
足够多的时间来再次反转方向。线程1随后会发现条件为false,假设出现虚假唤醒,然后返回睡眠状态。当方向再次翻转时,对于第三次(或者可能是第五次,或者对于任意大的奇数N
)时间,它最终会醒来。但是,如果线程1不参与,sync调用不足以导致另一次翻转。所有参与线程都必须调用sync。最新的线程总是会翻转,因此在您的示例中,除了m线程1(延迟的线程)之外,所有线程都会调用sync。m线程1最终会在它醒来后调用sync。如果在捕获点count
为0,那么翻转是否确实会发生不好的事情。您能详细说明一下吗?count目前仅公开,因为我使用lambda,我会将所有这些都更改为一个结构,该结构将大小作为一个成员函数的输入,没有任何参数。我不确定我是否理解这里的目标。在顶部,以下是可能的。线程1等待方向翻转。线程2翻转方向并通知所有线程。但是,在线程1有机会醒来并检查状态之前,其他线程调用sync
足够多的时间来再次反转方向。线程1随后会发现条件为false,假设出现虚假唤醒,然后返回睡眠状态。当方向再次翻转时,对于第三次(或者可能是第五次,或者对于任意大的奇数N
)时间,它最终会醒来。但是,如果线程1不参与,sync调用不足以导致另一次翻转。所有参与线程都必须调用sync。最新的线程总是翻转,因此在您的示例中,除了m线程1(延迟的线程)之外,所有线程都调用sync,m线程1最终会在它醒来并翻转后调用sync
std::mutex mutex;
std::condition_variable cv;
uint8_t size = 2;
uint8_t count = size;
uint8_t direction = -1;
const auto sync = [&size, &count, &mutex, &cv, &direction]() //.
{
{
std::unique_lock<std::mutex> lock(mutex);
auto current_direction = direction;
if (--count == 0)
{
count = size;
direction *= -1;
cv.notify_all();
}
else
{
cv.wait(lock,
[&direction, ¤t_direction]() //.
{ return direction != current_direction; });
}
}
};