C++多线程 (3):锁与智能锁

   互斥量 ,互斥锁(strd::mutex类):

        头文件#include

        简述:是个类对象。理解成一把锁,多个线程用lock()成员函数来加锁,

              只有一个线程能锁成功,锁成功的线程可以往下执行

       lock() (锁) 和unlock() (解锁) 要成对使用

步骤:     1) lock(),锁上共享数据

             2) unlock(),打开共享数据

        std::lock

                简述:是一个模板,用于对未上锁的锁们进行集体上锁

                使用前提:不能有锁提前上

#include
#include

using namespace std;

int main(void)
{
    std::mutex mtx1;
    std::mutex mtx2;
    //对mtx1,mtx2基体上锁
    std::lock(mtx1,mtx2);

    //需要手动解锁
    mtx1.unlock();    
    mtx2.unlock();

    return 0;
}

智能锁

    1)std::lock_guard 锁的守卫员或智能锁

        简述:是一个类模板,类似于智能指针,创建时上锁,析构时解锁

         std::adopt_lock 用于智能锁的第二个参数,如:

                std::lock_guardg(mtx,std::adopt_lock);   表明mtx提前已经上锁过了

//创建锁
std::mutex mtx1;
//将锁交给管理员
std::lock_guardguard1(mtx1);

//创建锁
std::mutex mtx2;
//将锁锁住
mtx2.lock();
//让管理员接纳已经上过锁的锁
std::lock_guardguard2(mtx2,std::adopt_lock);

    2)unique_lock 独锁

                简述:unique_lock取代lock_guard,是一个类模板,比lock_guard灵活,也是一个智能锁,

         可以转交所有权,但不能复制所有权,只能独权专制

         unique_lock的第二个参数:

         2.1.1)    std::adopt_lock    --->    unique_locku(mtx,std::adopt_lock);

                  使用前提:提前上锁(lock())

                  介绍:用于智能锁的第二个参数,表明这个互斥量已经上过锁了,这样unique_lock就不

                           会对这个进行互斥量枷锁

//创建锁
std::mutex mtx1;
//将锁交给管理员
std::unique_lockulock1(mtx1);

//创建锁
std::mutex mtx2;
//将锁锁住
mtx2.lock();
//让管理员接纳已经上过锁的锁
std::unique_lockulock2(mtx2,std::adopt_lock);

        2.1.2)    std::try_to_lock    --->    unique_locku(mtx,std::try_to_lock);

                作用:尝试拿锁,拿不到锁也不会卡死不动

                使用前提:不能自己提前加锁(lock())

//创建锁
std::mutex mtx;
//管理员尝试找锁
std::unique_lockulock(mtx,std::try_to_lock);

        2.1.3)    std::defer_lock        表示初始化一个没有加锁的互斥量
                    使用前提:不能自己提前上锁(lock())
                    简述:没有给mutex加锁,初始化了一个没有加锁的mutex

//创建锁
std::mutex mtx;
//管理员拿到锁先不上锁
std::unique_lockulock(mtx,std::defer_lock);

        2.2)unique_lock成员函数
                    lock()        加锁

                    unlock()    解锁

                   owns_lock()    判断自己是否拿到了锁,或者是否自己上了锁

                   try_lock()    尝试给互斥量加锁,如果拿到了锁,返回true,否则返回false

                   release()    返回它管理的mutex对象指针,释放所有权,和智能指针转交所有权一样

        2.3)转移所有权    
                    1.4.1)使用std::move()函数转移

                    1.4.2)返回局部变量,移交局部变量的所有权
                    
                    1.4.3)通过定义新的std::unique_lock锁,使用成员函数swap()进行交换,可以达到同样

                            的目的

                   1.4.4)通过定义新的std::unique_lock锁,在新锁定义时传入旧锁的release()函数,可做

                            到让旧锁释放权限的同时,新锁接管权限

死锁        

        简述:至少两个锁(互斥量)才能产生死锁

        发生情况:不同线程 上不同锁的顺序不同

         如:  线程A先上金锁,再上银锁

                 线程B线上银锁,再上金锁

         执行过程: 当A上了金锁后,B恰好上了银锁    
        
                -->    导致A没办法上银锁,B没办法上金锁,出现死锁现象

       避免死锁:保证不同线程上锁的顺序一样即可

#include
#include

using namespace std;
int main(void)
{
    std::mutex mtx1;
    std::mutex mtx2;

    //造成死锁的情况,两个线程上锁顺序不同,造成一定几率卡死
    thread t1(
        mtx1.lock();
        mtx2.lock();
        cout<<"线程t1执行中......"<

粒度

           粒度:就是锁住的代码

                        粒度细--->锁住代码量少    可能漏掉保护的数据

                        粒度粗--->锁住代码量多    影响执行效率               

你可能感兴趣的:(C++多线程,c++)