C++多线程

C++多线程

  1. 互斥量
    lock()和unlock()要成对使用
    lock_guard sbguard(myMutex);相当于使用了lock()和unlock()
    lock_guard构造函数执行了mutex::lock();在作用域结束时,调用析构函数,执行mutex::unlock()
    lock_guard加入adopt_lock后,在调用lock_guard的构造函数时,不再进行lock(),而且必须要先锁上;

    lock(myMutex1, myMutex2);//这个的好处就是不需要考虑解锁
    lock_guard<mutex> sbguard(myMutex1, adopt_lock);
    lock_guard<mutex> sbguard1(myMutex2, adopt_lock);
    

    std::lock(mutex1,mutex2……); 一次锁定多个互斥量(一般这种情况很少),用于处理多个互斥量;

  2. unique_lock
    unique_lock比lock_guard多出很多用法而且可以随时解锁,但是效率差一点(unique_lock默认情况下也是不需要自己加锁解锁);
    unique_lock的第二个参数
    std::adopt_lock:
    表示这个互斥量已经被lock(),即不需要在构造函数中lock这个互斥量了。
    std::try_to_lock:
    尝试用mutex的lock()去锁定这个mutex,但如果没有锁定成功,会立即返回,不会阻塞在那里;
    使用try_to_lock的原因是防止其他的线程锁定mutex太长时间,导致本线程一直阻塞在lock这个地方
    owns_locks()方法判断是否拿到锁,如拿到返回true
    std::defer_lock:
    如果没有第二个参数就对mutex进行加锁,加上defer_lock是始化了一个没有加锁的mutex,不给它加锁的目的是以后可以调用unique_lock的一些方法
    前提:不能提前lock
    release()
    mutex* ptx =
    myUniLock.release();所有权由ptx接管,如果原来mutex对象处理加锁状态,就需要ptx在以后进行解锁了。
    std::call_once():
    函数模板,该函数的第一个参数为标记,第二个参数是一个函数名(如a())。
    功能:能够保证函数a()只被调用一次。具备互斥量的能力,而且比互斥量消耗的资源更少,更高效。
    call_once()需要与一个标记结合使用,这个标记为std::once_flag;其实once_flag是一个结构,call_once()就是通过标记来决定函数是否执行,调用成功后,就把标记设置为一种已调用状态。

    	std::once_flag onceflag;
    	std::call_once(onceflag, MyThread);
    

    我认为call_once()和原子操作类似,原子操作就是在多线程中不会被打断的程序片段;原子操作比互斥量更胜一筹;原子操作一般都是指“不可分割的操作”,也就是说这种操作状态要么是完成的,要么是没完成的,不可能出现半完成状态。
    一般atomic原子操作,针对++、–、&=、|=是支持的。其他的可能不支持;

    #include<iostream>
    #include<thread>
    #include<string>
    #include<vector>
    #include<list>
    #include<mutex>
    #include<future>
     
    using namespace std;
     
    //我们封装了一个类型为int的对象,像操作一个int类型变量一样来操作这个g_mycont
    std::atomic<int> g_mycont = 0;
     
    void mythread()
    {
    	for (int i = 0; i < 1000000; i++)
    	{
    		//g_mycont++;//对应的操作是个原子操作(不会被打断)
    		//g_mycont += 1;
    		g_mycont = g_mycont + 1;  //结果不对,不是原子操作
    	}
    }
    int main()
    {
    	thread myobj(mythread);
    	thread myobj2(mythread);
     
    	myobj.join();
    	myobj2.join();
     
    	cout << "两个线程执行完毕,最终的g_mycont的结果是:" << g_mycont <<endl;
     
    	return 0;
    }
    

    std::atomic来代表原子操作,std::atomic是个模板。其实std::atomic这个东西是用来封装某一个类型的值的;多线程中一般用于计数,或者统计。

  3. 条件变量

    condition_variable
    第一个参数是一个锁,第二个参数是一个可调用对象。
    如果第二个参数返回true,wait()直接返回进入下一步。
    如果第二个参数返回false,那么wati()将解锁互斥量,并堵塞直到其他某个线程调用notify_one()成员函数为止。
    如果wait()没有第二个参数,那么就和第二个参数返回true的效果一样。

    std::mutex mymutex;
    std::unique_lock<std::mutex> uniquelock(mymutex);
    std::condition_variable condition;
    condition.wait(uniquelock, [this] {if (!msgRecvQueue.empty())
                                        return true;
                                    return false;
                                    });
    condition.wait(uniquelock);
    

    notify_one成员函数
    其他线程调用notify_one()将通知一个线程的wait()的状态唤醒后,wait恢复工作,如果wait并没有堵塞,那么此时notify_one调用可能就没有效果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值