【多线程】多线程锁住的是什么、std::lock_guard<std::mutex> locker(mutex_)

通常不直接使用 mutex,lock_guard更加安全, 更加方便。
lock_guard简化了 lock/unlock 的写法, lock_guard在构造时自动锁定互斥量, 而在退出作用域时会析构自动解锁, 保证了上锁解锁的正确操作, 正是典型的 RAII 机制。

#include <thread>
#include <mutex>

std::mutex mutex_;
void func() 
{
    {
        std::lock_guard<std::mutex> locker(mutex_);   //出作用域自动解锁
        //do some things...
    }
    mutex_.lock();
    //do some things...
    mutex_.unlock();
}


int main()
{
    std::thread t(func);
    t.join();
}

问题1:

std::lock_guard<std::mutex> locker(mutex_);这样同一句代码在多个位置出现,我以前不太了解的时候,不知道他们是不是管理的是同一个互斥锁mutex_

  • std::lock_guard<std::mutex> locker(mutex_);这句话很具有误导性,看着像是一个拷贝构造函数的使用,像是新创建了一个锁locker,并把一个互斥量mutex_拷贝给他。实则并非如此,而是一个std::lock_guard构造函数传入一个std::mutex类的参数。

  • 这句话传入的参数是一个互斥量mutex_,并不是一个lock_guard对象,所以不是拷贝构造。 std::lock_guard类的构造函数禁用拷贝构造,且禁用移动构造。std::lock_guard类除了构造函数和析构函数外没有其它成员函数

  • 它是对互斥锁变量mutex_进行所有权获取,并不是每一处就重新创建一个锁进行锁住,这样毫无意义,因为如果是这样的话,每一个线程到了这句话的位置都会直接创建锁,不会有别人来抢夺。

  • 正确理解:std::lock_guard<std::mutex> locker(mutex_);是对互斥锁变量mutex_进行管理,在这句话后面的作用域内,代码都处于mutex_上锁状态,别的位置代码获取这个锁mutex_会失败。他们的目的就是为了保护同一个共享内存区域不会被多线程同时访问(同时读和写、或 同时写和写)。

  • std::lock_guard对象构造时,传入的mutex对象(即它所管理的mutex对象)会被当前线程锁住。在lock_guard对象被析构时,它所管理的mutex对象会自动解锁,不需要程序员手动调用lockunlockmutex进行上锁和解锁操作。

  • lock_guard对象并不负责管理mutex对象的生命周期,lock_guard对象只是简化了mutex对象的上锁和解锁操作,方便线程对互斥量上锁,即在某个lock_guard对象的生命周期内,它所管理的锁对象会一直保持上锁状态;而lock_guard的生命周期结束之后,它所管理的锁对象会被解锁。程序员可以非常方便地使用lock_guard,而不用担心异常安全问题。
    std::lock_guard在构造时只被锁定一次,并且在销毁时解锁。这段话摘自C++11中std::lock_guard的使用

C++11中std::mutex的使用.


问题2:

std::lock_guard<std::mutex> locker(mutex_);这句话是锁定mutex_这个互斥量,避免其他线程获取这个互斥量吗? 还是说,只锁住这句话之后的代码块,避免别的线程访问该代码块的共享变量???

  • 答:是锁住这个互斥量。因为一旦有一个线程的某段代码锁住了这个互斥量,其他线程就获取不了这个锁的权限了。使用同一个互斥量在不同的地方锁住,是因为这几个地方代码肯定会访问同一个变量(或者说共享内存区域),不然不需要使用锁。只有在多线程下才需要使用锁。哪怕只有一个地方使用锁,还是必要的,因为不同线程都在同一片代码块进行写操作时,也需要加锁防止同时在这个地方写造成写数据混乱。

  • 在代码的多处都使用这同一句代码std::lock_guard<std::mutex> locker(mutex_);,这些地方都争抢这获取同一个互斥量mutex_,肯定是这不同的地方都访问了同一片共享内存,或者限制访问资源,此时只能有一块代码能够获得这个锁,进而只有某一时刻只有该代码处能访问该资源。

  • 简而言之,对于位置A和位置B对同一个互斥量mutex上锁std::lock_guard<std::mutex> locker(mutex_);,作用就是:

  • 1.同一位置A处上锁,是防止线程1在位置A的时候,线程2在位置A该内存区域;或者,防止线程1在位置A的时候,线程2在位置A该内存区域;

  • 2.不同位置A和B都上锁,是防止线程1在位置A的时候,线程2在位置B该内存区域,或者线程1在位置A的时候,线程2在位置B该内存区域。

  • 上面是我个人理解,如有错误,望各位大佬指正。

void func1(){
  //位置A
  std::lock_guard<std::mutex> locker(mutex_);
  ....
}

void func2(){
  //位置B
  std::lock_guard<std::mutex> locker(mutex_);
  ....
}
  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值