使用互斥锁同步线程

Synchronize threads using mutex

本文关键字:同步 线程      更新时间:2023-10-16

我试图理解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使用这两个线程

问题是,两个线程将进入一个"无限"循环1秒,他们会贪婪的互斥锁。在两个函数中执行一次print,看看哪个线程获得锁的次数更多。

互斥锁用于同步对资源的访问,这样线程就不会读写不完整或损坏的数据,也不会创建一个整洁的序列。

如果你想在执行结束时保持该值为100,你需要使用一个信号量,以便对变量的访问有一个有序的序列。

我认为,您想要的是向减法线程发出信号,表明您刚刚成功地添加了添加线程,反之亦然。您必须额外地传达信息,即下一个线程是哪个。一个朴素的解决方案:

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()完成它的工作,然后再尝试获取锁。

为了避免繁忙的等待,您可以选择一个条件变量,而不是尝试只使用单个互斥锁。您可以在添加或减去条件变量之前等待(),然后通知()等待线程。