C++多线程学习[五]:RAII锁

一、什么是RAII

使用局部对象来控制资源的技术,即它的生命周期由操作系统来管理,无需人工的介入。
为什么要采用RAII技术呢? 主要是在开发过程中资源的销毁容易忘记,容易造成死锁或内存泄露。

{}为一个区域 ,这里锁的是一块区域。不用在冗余的写mutex.lock()和mutex.unlock();

二、手动实现RAII管理mutex资源

#include<iostream>
#include<thread>
#include<mutex>
using namespace std;

class Tmutex
{
   
public:
	Tmutex(mutex& mtx) : mtx_(mtx)
	{
   
		cout << "Lock" << endl;
		//mtx_.lock();
	}

	~Tmutex()
	{
   
		cout << "UnLock" << endl;
		//mtx_.unlock();
	}
private:
	mutex &mtx_;
};

static mutex mtx;
void Test(int i)
{
   
	Tmutex lock(mtx);
	if (i == 1)
	{
   
		cout << " i = 1 " << endl;
	}
	else if (i == 2)
	{
   
		cout << " i = 2" << endl;
	}
	else 
	{
   
		cout << " i = " <<i<< endl;
	}

}

int main() 
{
   
	Test(1);
	Test(2);
	Test(3);
	return 0;
}

在这里插入图片描述

在这种方式中,lock 是一个对象,它被定义为互斥锁 mtx 的一个“保护者”(guard)。当创建 lock 对象时,在其构造函数中会自动执行 mtx.lock() 方法,从而获取互斥锁,确保当前线程拥有了对共享资源的独占访问权。而在 lock 对象生命周期结束时,其析构函数会自动调用 mtx.unlock() 方法,从而释放互斥锁,确保其他线程可以继续访问共享资源。

三、C++11 RAII控制锁lock_guard

在这里插入图片描述
可以看到 lock_guard源码中的构造会自动上锁,析构会自动解锁。

#include<iostream>
#include<thread>
#include<mutex>

using namespace std;

static mutex mtx;

void Test(int i)
{
   
	lock_guard<mutex> lock(mtx);
	for (;;)
	{
   
		cout << i << endl;
		this_thread::sleep_for(500ms);
	}
}
int main() 
{
   
	for (int i = 0; i < 3; i++)
	{
   
		thread th(Test, i + 1);
		th.detach();
	}
	getchar();
	return 0;
}

在这里插入图片描述
这里三个线程,但是i = 2 这个线程被锁住,

当然它还有另一个构造函数,adopt_lock_t用来判断是否已经上锁。
在这里插入图片描述
在这里,因为lock_guard锁的区域并没有检查到是否上锁,因此会报错。
(和下面unique_lock一样)
在这里插入图片描述

在这里插入图片描述
我们在他之前锁上
在这里插入图片描述

这里它检测到前面已经上锁,因此会通过。

四、unique_lock

在这里插入图片描述
源码中有四个构造函数。
主要的是后三个(括号内指的是unique_lock对象)

  • adopt_lock 文章前面涉及到(已经拥有锁,不加锁,出栈区后会释放)

  • defer_lock (延后拥有锁,不加锁,出栈区后不释放,加锁后,退出栈区释放)
    在这里插入图片描述
    在这里插入图片描述
    锁加在哪里都可以,这里3个线程都延时后i = 2 的先上锁。 因为不释放,所以不加锁的话这3个线程会一直运行,而不发生阻塞,直到其中一个被上锁。

  • try_to_lock(尝试获得互斥的所有权而不阻塞,获取失败退出栈区不会释放,通过owns_locc()函数判断 )
    在这里插入图片描述
    如果已经锁上,会尝试读取是否上锁,因为前面已经上锁,因此它不会再次上锁,所以进入else情况

当然它也可以自己上锁
在这里插入图片描述

相关推荐

  1. c#线 使用lock

    2024-02-08 22:14:02       36 阅读
  2. 2024.4.9记——C++线系列文章()之死

    2024-02-08 22:14:02       34 阅读
  3. C# 线编程:线与无并发

    2024-02-08 22:14:02       34 阅读
  4. C# 中线的使用经验

    2024-02-08 22:14:02       37 阅读
  5. C++线编程中的详解

    2024-02-08 22:14:02       24 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-08 22:14:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-08 22:14:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-08 22:14:02       82 阅读
  4. Python语言-面向对象

    2024-02-08 22:14:02       91 阅读

热门阅读

  1. TCP和UDP相关问题(重点)(3)——3.HTTP基于TCP还是UDP?

    2024-02-08 22:14:02       55 阅读
  2. 如何制作一款3D FPS游戏

    2024-02-08 22:14:02       55 阅读
  3. 什么是jieba?

    2024-02-08 22:14:02       80 阅读
  4. SQL世界之命令语句Ⅱ

    2024-02-08 22:14:02       48 阅读
  5. Mybatis源码解析之——数据源池化技术(二)

    2024-02-08 22:14:02       44 阅读
  6. 系统架构评估

    2024-02-08 22:14:02       50 阅读
  7. c++ 子进程交互 逻辑

    2024-02-08 22:14:02       56 阅读
  8. dockerfile 详细讲解

    2024-02-08 22:14:02       49 阅读