简体   繁体   English

使用互斥锁同步线程

[英]Synchronize threads using mutex

I'm trying to understand C++ Multithreading and synchronize between many threads. 我试图理解C ++多线程并在许多线程之间进行同步。 Thus I created 2 threads the first one increments a value and the second one decrements it. 因此,我创建了2个线程,第一个增加一个值,第二个减少它。 what I can't understand why the resulted value after the execution is different than the first one, since I added and subtracted from the same value. 我不明白为什么执行后的结果值与第一个不同,因为我在相同的值上加减了。

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;
}

Output 产量

critical section value at the start 100 开始时的临界区值100

critical section value at the end 220 末端的临界截面值220

So what I need is how to keep my value as it's, I mean counter equal to 100 using those two threads. 所以我需要的是如何保持自己的价值,我的意思是使用这两个线程将计数器等于100。

The problem is that both threads will get into an "infinite" loop for 1 second and they will get greedy with the mutex. 问题在于两个线程都将进入“无限”循环1秒钟,并且它们将对互斥量感到贪婪。 Do a print in both functions and see which thread gets the lock more often. 在这两个函数中进行打印,然后查看哪个线程更频繁地获得锁定。

Mutexes are used to synchronize access to resources so that threads will not read/write incomplete or corrupted data, not create a neat sequence. 互斥锁用于同步对资源的访问,以便线程不会读/写不完整或损坏的数据,不会创建整齐的序列。

If you want to keep that value at 100 at the end of execution you need to use a semaphore so that there will be an ordered sequence of access to the variable. 如果要在执行结束时将该值保持为100,则需要使用信号量,以便对变量进行有序访问。

I think, what you want is to signal to the subtracting thread, that you just have sucessfully added in the add thread, and vice versa. 我认为,您要向减法线程发出信号,即您已成功添加了加法线程,反之亦然。 You'll have to additionally communicate the information, which thread is next. 您还必须另外传达信息,接下来是哪个线程。 A naive solution: 一个幼稚的解决方案:

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;
    }
  }
}

Now add() will busy wait for sub() to do its job before it will try and acquire the lock again. 现在,add()将忙于等待sub()完成其工作,然后再尝试获取该锁。

To prevent busy waiting, you might chose a condition variable, instead of trying to only use a single mutex. 为了避免繁忙的等待,您可以选择条件变量,而不是尝试仅使用单个互斥锁。 You can wait() on the condition variable, before you add or subtract, and notify() the waiting thread afterwards. 您可以在添加或减去之前在条件变量上使用wait(),然后在等待线程之前通知()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM