C++lock、unlock、lock_guard和condition_variable锁

lock、unlock

lock()和unlock()函数必须同时成对存在,不存在一多一少的情况;

lock()调用线程将锁住该互斥量;

  1. 若该互斥量当前没有被锁住,则进行加锁;
  2. 若当前互斥量被其他线程锁住,则当前的调用线程被阻塞;
  3. 若当前互斥量被当前调用的线程锁住,则会产生死锁,因为同一个线程不允许锁两次;

 unlock()进行解锁操作,释放互斥量的所有权;

#include <iostream>
#include <thread>
#include <mutex>
#include <deque>

class lock_unlock{
public:
    lock_unlock(){}
    void WriteOperate(){
        for(int i=0;i<1000;i++){
            nums_mutex.lock();
            std::cout<<"写入一个元素"<<std::endl;
            nums_deque.push_back(i);
            nums_mutex.unlock();
        }
    }

    void ReadOperate(){
        for(int i=0;i<1000;i++){
            nums_mutex.lock();
            if(!nums_deque.empty()){
                std::cout<<"读出第一个元素"<<nums_deque.front()<<std::endl;
                nums_deque.pop_front();  
            }
            nums_mutex.unlock();
        }
    }
private:
    std::deque<int> nums_deque;
    std::mutex nums_mutex;
};

int main(int argc,char* argv[]){
    lock_unlock lock;
    std::thread nums_thread1(&lock_unlock::WriteOperate,std::ref(lock));
    std::thread nums_thread2(&lock_unlock::ReadOperate,std::ref(lock));

    /*线程阻塞*/
    nums_thread1.join();
    nums_thread2.join();
    std::cout<<"执行完毕!"<<std::endl;
    return 0;
}

lock_guard 

/*lock_guard()是一个类模板,里面已经存在lock()和unlock()函数,因此只需要一个即可*/

#include <iostream>
#include <thread>
#include <mutex>
#include <deque>

class lock_guard{
public:
    void WriteOperate(){
        for(auto i=0;i<1000;i+=2){
            std::lock_guard<std::mutex> nums_lockguard(nums_mutex);
            nums_deque.push_back(i);
        }
    }
    
    void ReadOpreate(){
        for(auto i=0;i<1000;i++){
            std::lock_guard<std::mutex> nums_lockguard(nums_mutex);
            if(!nums_deque.empty()){
                std::cout<<nums_deque.front()<<std::endl;
                nums_deque.pop_front();
            }
        }
    }
private:
    std::deque<int> nums_deque;
    std::mutex nums_mutex;
};

int main(int argc,char*[]){
    lock_guard guard;
    std::thread nums_thread1(&lock_guard::WriteOperate,std::ref(guard));
    std::thread nums_thread2(&lock_guard::ReadOpreate,std::ref(guard));
    
    /*线程阻塞*/ 
    nums_thread1.join();
    nums_thread2.join();
    std::cout<<"执行完毕!"<<std::endl;
    return 0;
}

condition_variable

condition_variable(条件变量),通俗的将线程根据条件去拿锁,若不符合条件则休眠,直到有线程唤醒它才会继续去竞争锁,用于线程同步,只能配合unique_lock使用,前面3个wait函数需要传入一个已经上锁的变量unique_lock<mutex>,此外第二个参数传入lambda表达式用于防止虚假唤醒;而condition_variable_any可以应用于任意的lock;

  1. wait:阻塞自己,等待唤醒;wait函数存在两个参数,第一个是unique_lock,第二个参数是lambda表达式或其他函数,返回值是bool,若第二个参数不传入,默认条件判断为false,相当于互斥锁,即每次都需要notify唤醒,如果所有唤醒线程结束运行,而没有线程唤醒它则休眠堵塞;
  2. wait_for:阻塞自己,等待唤醒,最多等待一段时间;
  3. wait_unti:阻塞自己,等待唤醒,最多等待到某个时刻;
  4. notify_one:唤醒一个等待在这个条件变量上的线程,若线程没有进入休眠状态则无效;
  5. notify_all:唤醒所有等待在这个条件变量上的线程;
#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <list>

class condition_variables{
public:
    void WriteOperate(){
        for(auto i=0;i<100;i+=2){
            std::unique_lock<std::mutex> mg_lock(mg_mutex);
            message.push_back(i);
            mg_condv.notify_one();/*唤醒线程*/     
        }
    }

    void ReadOperate(){
        for(auto i=0;i<100;i+=2){
            std::unique_lock<std::mutex> mg_lock(mg_mutex);
            /*lambda表达式无参数传入可以省略,this类指针,值传递,返回值bool型,自动匹配类型可省略*/
            mg_condv.wait(mg_lock,[this]{return !message.empty();});
            std::cout<<message.front()<<std::endl;
            message.pop_front();
        }
    }

private:
    std::list<int> message;
    std::mutex mg_mutex;
    std::condition_variable mg_condv;
};

int main(int argc,char* argv[]){
    condition_variables cond;
    std::thread W_thread(&condition_variables::WriteOperate,&cond);
    std::thread R_thread(&condition_variables::ReadOperate,&cond);

    W_thread.join();
    R_thread.join();
    return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路上的追梦人

您的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值