我正在尝试理解C ++多线程并在多个线程之间进行同步。 因此,我创建了2个线程,第一个增加了一个值,第二个减少了它。我无法理解为什么执行后的结果值与第一个不同,因为我加了相同的值并从中减去了。
static unsigned int counter = 100;
static bool alive = true;
static Lock lock;
std::mutex mutex;
void add() {
while (alive)
{
mutex.lock();
counter += 10;
std::cout << "Counter Add = " << counter << std::endl;
mutex.unlock();
}
}
void sub() {
while (alive)
{
mutex.lock();
counter -= 10;
std::cout << "Counter Sub = " << counter<< std::endl;
mutex.unlock();
}
}
int main()
{
std::cout << "critical section value at the start " << counter << std::endl;
std::thread tAdd(add);
std::thread tSub(sub);
Sleep(1000);
alive = false;
tAdd.join();
tSub.join();
std::cout << "critical section value at the end " << counter << std::endl;
return 0;
}
开始时的临界区值100
结束时的临界区值220
所以我需要的是如何保持我的价值,我的意思是使用这两个线程的计数器等于100。
答案 0 :(得分:2)
问题在于两个线程都会进入“无限”状态。循环1秒钟,他们将与互斥锁贪婪。在两个函数中进行打印,并查看哪个线程更频繁地获取锁定。
互斥锁用于同步对资源的访问,以便线程不会读/写不完整或损坏的数据,也不会创建整齐的序列。
如果要在执行结束时将该值保持为100,则需要使用信号量,以便对变量进行有序的访问序列。
答案 1 :(得分:1)
我认为,你想要的是向减法线程发出信号,你刚刚在添加线程中成功添加,反之亦然。您还必须另外传达信息,下一个线程。一个天真的解决方案:
bool shouldAdd = true;
add() {
while( alive ) {
if( shouldAdd ) {
// prefer lock guards over lock() and unlock() for exception safety
std::lock_guard<std::mutex> lock{mutex};
counter += 10;
std::cout << "Counter Add = " << counter << std::endl;
shouldAdd = false;
}
}
}
sub() {
while( alive ) {
if( !shouldAdd ) {
std::lock_guard<std::mutex> lock{mutex};
counter -= 10;
std::cout << "Counter Sub = " << counter << std::endl;
shouldAdd = true;
}
}
}
现在add()将忙于等待sub()完成其工作,然后再尝试获取锁。
为了防止忙碌等待,您可以选择条件变量,而不是仅尝试使用单个互斥锁。在添加或减去之前,你可以在条件变量上等待(),然后在等待线程中通知()。