C++互斥锁std::mutex


std::mutex 是C++11 中最基本的互斥量,std::mutex 对象提供了独占所有权的特性——即不支持递归地对 std::mutex 对象上锁。

std::mutex 成员函数

构造函数

std::mutex不允许拷贝构造,也不允许 move 拷贝,最初产生的 mutex 对象是处于 unlocked 状态的。

lock()

1、如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁。
2、 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。
3、 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。

unlock()

解锁,释放对互斥量的所有权。

try_lock()

尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞。线程调用该函数也会出现下面 3 种情况:
1、 如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量。
2、 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉。
3、 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。(这一条存疑,实测单线程内先lock再trylock,不会死锁,会有1ms以内的停顿,trylock返回false)

std::lock_guard

lock_guard是一个互斥量包装程序,它提供了一种方便的RAII(Resource acquisition is initialization )风格的机制来在作用域块的持续时间内拥有一个互斥量。
创建lock_guard对象时,它将尝试获取提供给它的互斥锁的所有权。当控制流离开lock_guard对象的作用域时,lock_guard析构并释放互斥量。

1、创建即加锁,作用域结束自动析构并解锁,无需手工解锁
2、不能中途解锁,必须等作用域结束才解锁
3、不能复制

std::unique_lock

unique_lock是lock_guard的升级版,它允许延迟锁定,限时深度锁定,递归锁定,锁定所有权的转移以及与条件变量一起使用。

1、创建时可以不锁定(通过指定第二个参数为std::defer_lock),而在需要时再锁定
2、可以随时加锁解锁
3、作用域规则同 lock_grard,析构时自动释放锁
4、不可复制,可移动
5、条件变量需要该类型的锁作为参数(此时必须使用unique_lock)

lock_guard 和unique_lock 并不管理 std::mutex 对象的生命周期,在使用 lock_guard 的过程中,如果 std::mutex 的对象被释放了,那么在 lock_guard 析构的时候进行解锁就会出现空指针错误。

std::mutex实测代码

#include <mutex>
#include <unistd.h>
std::mutex g_mutex;
pthread_t Tid[10];
void* threadfunc0(void*)
{
    
    
    printf("threadfunc0\n");
    std::unique_lock<std::mutex> locker(g_mutex);
//    g_mutex.unlock();/*如果执行,则立即打印threadfunc1,after lock,不会等待5秒*/
    sleep(5);
    return nullptr;
}

void* threadfunc1(void*)
{
    
    
    printf("threadfunc1\n");
    std::unique_lock<std::mutex> locker(g_mutex);
    if(g_mutex.try_lock() == true)//不会死锁,返回false,有1ms内的停顿
    {
    
    
        printf("try_lock\n");
        g_mutex.unlock();
    }

    printf("threadfunc1,after lock\n");
    return nullptr;
}

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{
    
    
    ui->setupUi(this);
    setbuf(stdout,nullptr);

    pthread_create(&Tid[0],nullptr,threadfunc0,nullptr);
    usleep(100);
    pthread_create(&Tid[1],nullptr,threadfunc1,nullptr);
}

打印

threadfunc0
threadfunc1
(等待5秒)
threadfunc1,after lock

猜你喜欢

转载自blog.csdn.net/weixin_40355471/article/details/129853726