使用互斥锁同步线程

时间:2015-09-01 13:22:43

标签: c++ multithreading

我正在尝试理解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。

2 个答案:

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

为了防止忙碌等待,您可以选择条件变量,而不是仅尝试使用单个互斥锁。在添加或减去之前,你可以在条件变量上等待(),然后在等待线程中通知()。