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

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

        头文件#include<mutex>

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

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

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

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

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

        std::lock

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

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

#include<iostream>
#include<mutex>

using namespace std;

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

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

    return 0;
}

智能锁

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

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

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

                std::lock_guard<std::mutex>g(mtx,std::adopt_lock);   表明mtx提前已经上锁过了

//创建锁
std::mutex mtx1;
//将锁交给管理员
std::lock_guard<std::mutex>guard1(mtx1);

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

    2)unique_lock 独锁

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

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

         unique_lock的第二个参数:

         2.1.1)    std::adopt_lock    --->    unique_lock<std::mutex>u(mtx,std::adopt_lock);

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

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

                           会对这个进行互斥量枷锁

//创建锁
std::mutex mtx1;
//将锁交给管理员
std::unique_lock<std::mutex>ulock1(mtx1);

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

        2.1.2)    std::try_to_lock    --->    unique_lock<std::mutex>u(mtx,std::try_to_lock);

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

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

//创建锁
std::mutex mtx;
//管理员尝试找锁
std::unique_lock<std::mutex>ulock(mtx,std::try_to_lock);

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

//创建锁
std::mutex mtx;
//管理员拿到锁先不上锁
std::unique_lock<std::mutex>ulock(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<iostream>
#include<mutex>

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

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

    t1.join();
    t2.join();

    return 0;
}

粒度

           粒度:就是锁住的代码

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

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

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多线程操作Vector可以提高程序的运行效率和并发性。Vector是一个线程安全的容器,可以被多个线程同时访问和修改。但是在多线程操作Vector时,需要注意以下几点。 首先,多线程操作Vector需要进行同步控制,以避免数据竞争和并发访问的问题。可以通过使用互斥(mutex)来实现线程间的互斥操作,保证在一个线程访问Vector时,其他线程不能同时进行写操作。 其次,应该注意避免在迭代器遍历Vector的同时进行修改操作,可能会导致迭代器失效或产生未定义的行为。一种解决方案是使用智能指针,可以在遍历时保持Vector的引用计数,防止迭代器失效。 另外,多线程操作Vector还可以通过分割Vector的部分来实现并行处理,提高程序的执行效率。可以将Vector分割为多个子Vector,每个线程处理一个子Vector的数据,最后再将结果合并。 在使用多线程操作Vector时,还需注意线程间的数据同步和线程安全的问题。可以使用条件变量(condition variable)来实现线程间的通信和同步。同时,应考虑使用原子操作(atomic operation)来保证对Vector的操作是原子的,从而避免数据不一致的问题。 总之,多线程操作Vector可以提高程序的性能和并发性,但同时也需要谨慎处理同步控制、迭代器失效和数据同步等问题,以确保线程安全和程序的正确性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值