c++ - 这是 boost 条件变量的正确使用吗?

标签 c++ multithreading boost

我编写了以下程序,使用 boost 条件变量交替递增和加倍计数器(先递增)。任何人都可以告诉我这是否是 boost 条件变量的正确使用。它工作正常。我不明白在等待函数调用中使用锁。 condition.wait(lock) 是什么意思?例如,在此程序中递增和乘法两个作用域锁的用途是什么。我怎样才能避免它们?

#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/bind.hpp>
#include <boost/thread/locks.hpp>
#include <boost/thread/condition_variable.hpp>
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;

int counter=0;
boost::mutex m1,m2;
bool incremented=false,multiplied=false;
boost::condition_variable c1,c2;
void Increment()
{
    {
        boost::mutex::scoped_lock lk(m1);
        counter++;
        incremented = true;
        c1.notify_one();

        while(!multiplied)
            c2.wait(lk);
        multiplied=false;

    }   
}
void Multiply()
{
    {
        boost::mutex::scoped_lock lk(m2);
        while(!incremented)
            c1.wait(lk);
        incremented = false;
        counter = counter*2 ;
        multiplied = true;
        c2.notify_one();
    }
}

void IncrementNtimes(int n){

    for(int i=0;i<n;i++){
        Increment();
    }
}

void MultiplyNtimes(int n){

    for(int i=0;i<n;i++){
        Multiply();
    }
}
int main(int argc, char* argv[])
{
    srand ( time(NULL) );

    boost::thread thrd1(boost::bind(&IncrementNtimes,20));
    boost::thread thrd2(boost::bind(&MultiplyNtimes,20));
    thrd1.join();
    thrd2.join();
    cout<<"Main counter is:"<<counter<<endl;
    return 0;
}

最佳答案

不,这是不正确的。您快完成了,但最大的问题是乘法和增量函数应该使用相同互斥体。

互斥量是提供互斥的对象。换句话说,互斥锁的意义在于防止两个线程同时接触同一个变量并导致不可预测的结果。互斥锁有点像一个 token ,一次一个线程持有,赋予它访问某个变量(或一组变量)的“权利”。在这种情况下,您试图保护的变量是 counter。必须有一个且只有一个互斥量控制访问计数器的权利。在您的情况下,每个线程都会持有自己的 token ,它认为它有权访问计数器,因此会出现不可预测的行为。

您通过锁定互斥量来“持有”它。这就是锁的意义所在,这就是为什么你无法“避开”它们。作用域锁的全部意义在于,假设您只有一个互斥体 m,当其中一个线程持有 m 上的锁时,另一个线程保证不会也持有 m 上的锁。如果您的编码正确,锁定 m 应该是访问 counter 的先决条件,因此 counter 的值应该是可预测的.

现在,关于 wait()。对 wait() 的调用意味着“我放弃了对这个互斥体的锁定,直到其他人发出这种情况的信号,然后我想要它回来”。同时,线程停止。所以假设你只有一个互斥量 m 和一个条件 c,并且 lkm 上的一个锁, c.wait(lk) 行表示线程将放弃 m 上的锁 lk 然后暂停执行直到其他线程调用 c.notify_one()(或 c.notify_all())。当等待线程从对 wait() 的调用返回时,它将自动重新获得 m 上的锁 lk 并且因此被允许再次访问计数器

最后,这些 boost 锁是“作用域”锁。这意味着它们会在销毁时自动释放(当它们超出范围时)。因此在这种情况下,每个函数都持有其锁直到它退出,除非它放弃其锁以等待并暂停执行以等待信号。

关于c++ - 这是 boost 条件变量的正确使用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2164910/

相关文章:

c++如何让用户输入方程式进行评估

c++ - 使用 C++ 函数将二维数组转换为文本

c++ - 为什么 omp_set_num_threads( omp_get_num_threads() ) 会改变任何东西?

linux - 使用 kill -9 杀死线程时发生了什么

java - 创建的 Runnables 的 lambda 的不同行为

c++ - SDL2 中的多个显示

c++ - QObject::connect() 带有枚举参数

python 的 C++ 库 - 链接问题

c++ - boost::asio::connect() 未找到

c++ - 编译 boost::math 的性能测试应用程序