某日二师兄加入XXX科技公司的C++工程师开发岗位第31面:

面试官:什么是锁?有什么作用?

二师兄:在C++中,锁(Lock)是一种同步工具,用于爱护共享资源,避免多个线程同时拜访,从而防止数据竞争和不统一。

面试官:有哪些锁?

二师兄:从品种上分,能够分为一般锁、读写锁、递归锁等品种。

二师兄:从实现上分,能够分为互斥锁、自旋锁、信号量、条件变量等。

面试官:互斥锁如何应用?

二师兄:在C++11之前,C++便准层面并没有定义锁,锁的利用要依赖于平台。Linux下应用pthread库中的mutex

#include <pthread.h>pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_lock(&mutex_);//被爱护的区域pthread_mutex_unlock(&mutex_);
二师兄:C++11引入了std::mutex,对立了各个平台上互斥锁的应用:
#include <mutex>std::mutex mutex_;mutex_.lock();//被爱护的区域mutex_.unlock();

面试官:pthread_mutexstd::mutex有没有非阻塞的api

二师兄:有的,别离是pthread_mutex_trylock()try_lock(),当获取不到锁时这两者并不阻塞以后线程,而是立刻返回。须要留神的是,当pthread_mutex_trylock()获取到锁时返回0,而std::mutex::try_lock()办法获取不到锁时返回false

面试官:std::lock_guardstd::unique_lock用过吗?

二师兄:用过。

面试官:两者有什么相同点和不同点?

二师兄:相同点是两者都应用RAII(资源获取即初始化)技术实现的锁,反对主动上锁,主动解锁。

二师兄:不同点次要包含三个方面:

1.灵活性:std::unqiue_lock的灵活性要高于std::lock_guradstd::unique_lock能够在任何工夫解锁和锁定,而std::lock_guard在结构时锁定,在析构时解锁,不能手动管制。

2.所有权:std::unique_lock反对所有权转移,而std::lock_gurad不反对。

3.性能:因为std::unique_lock的灵活性更高,它的性能可能会略微低一些。

面试官:能实现一个lock_gurad吗?

二师兄:我尝试一下:

class lock_guard{    explicit lock_guard(std::mutex& m):mutex_(m)    {        mutex_.lock();    }    ~lock_guard()    {        mutex_unlock();    }private:    std::mutex& mutex_;};

面试官:为什么会产生死锁?

二师兄:当过程A持有锁1申请锁2,过程B持有锁2申请锁1时,两者都不会开释本人的锁,两者都须要对方的锁,就会造成死锁。当然事实中可能比这要简单,但原理是雷同的。

面试官:如何防止死锁?

二师兄:次要从以下几个方面动手:

1.防止循环期待,如果须要在业务中获取不同的锁,保障所有业务依照雷同的程序获取锁。

2.应用超时锁,当锁超时时,主动开释锁。

3.应用try_lock,当锁被占用时,返回false并继续执行。

4.锁的粒度尽量要小,只爱护竟态数据而不是整个流程。

面试官:晓得adopt_lock_t/defer_lock_t/try_to_lock_t这三种类型的用法吗?

二师兄:额。。不晓得。。

面试官:好的,回去等告诉吧。

让咱们来看看最初一个问题:

晓得adopt_lock_t/defer_lock_t/try_to_lock_t这三种类型的用法吗?

adopt_lock_t/defer_lock_t/try_to_lock_t都是空类,次要示意std::lock_guradstd::unqiue_lock的默认结构中的操作:

adopt_lock_t:默认互斥量已被以后线程锁定,不应用lock()办法对互斥量加锁:

std::mutex mtx_;mtx_.lock();    //lock{    std::lock_guard<std::mutex> lock_(mtx_,std::adopt_lock);    //这里默认以后线程曾经对mtx_加过锁    ...}//unlock

defer_lock_t:尽管我领有了std::mutex的援用,然而在构造函数中并不调用lock()办法对互斥量加锁:

std::mutex mtx_;{    std::unique_lock<std::mutex> ulock_(mtx_,std::defer_lock);    //这里并没有加锁    ulock_.lock();    if(ulock_.owns_lock())    {        //locked    }else    {        //unlocked    }}//if locked,unlock

try_to_lock_t:在构造函数执行是并不是应用lock()办法加锁,而是应用try_lock()办法加锁:

std::mutex mtx_;{    std::unique_lock<std::mutex> ulock_(mtx_,std::try_to_lock);    //这里mtx_如果没有被锁定,则加锁胜利,否则加锁失败    if(ulock_.owns_lock())    {        //locked    }else    {        //unlocked    }}//if locked,unlock

adopt_lock_t能够用于std::lock_guradstd::unique_lock,而defer_lock_t/try_to_lock_t只能用于std::unique_lock

关注我,带你21天“精通”C++!(狗头)