C++11多线程: mutex(互斥元)


由C++标准提供的保护共享数据的最基本机制是:互斥元 (mutex 全称为: mutual exclusive
在访问共享数据前, 锁定lock)与该数据相关的互斥元,当访问数据结构完成后, 解锁unlock)该互斥元。线程库一旦一个线程已经锁定某个互斥元,所有其他试图锁定相同互斥元的线程都必须等待,直到成功锁定了该互斥元的线程解锁此互斥元。
互斥元是C++中最常见的数据保护机制。
在C++中,通过构造std::mutex的实例创建互斥元,调用成员函数lock()来锁定它,调用成员函数unlock()来解锁它。

mutex(互斥元)

案例 1

线程对象th1通过传入的线程函数print_block,打印50个*
线程对象th2通过传入的线程函数print_block,打印50个$

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

mutex mtx; // mutex for critical section

void print_block( int n, char c) {

	// critical section (exclusive access to std::cout signaled by locking mtx):
	mtx.lock();//加锁

	for( int i = 0; i<n; ++i) { std:: cout<< c; }
	std:: cout<< '\n';

	mtx.unlock();//释放锁
}

int main(int argc, char *argv[])
{	
	std::thread th1(print_block, 50, '*');
	std::thread th2(print_block, 50, '$');

	th1.join();
	th2.join();

	return 0;
}

在这里插入图片描述
在这里插入图片描述

案例2

线程th1和线程th2,都通过传入的线程函数print_global_var,分别对全局变量a,进行自增20次。

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

int a = 0;
void print_global_var(){
	
	for(int i=0; i<20; i++)
	{
		mtx.lock();//加锁
		thread::id tid = this_thread::get_id();
		a++;
		cout << "tid:" << tid << " a:" << a << endl;
		mtx.unlock();//解锁
	}
	
}
int main(int argc, char *argv[])
{	
	std::thread th1(print_global_var);
	std::thread th2(print_global_var);

	th1.join();
	th2.join();

	return 0;
}

critical section: 指的是每个线程中访问临界资源的那段代码,不论是硬件临界资源,还是软件临界资源,多个线程必须互斥地对它进行访问。就是指的加锁和解锁之间的那段代码。
在这里插入图片描述
在这里插入图片描述

lock_guard()

在C++中,通过构造std::mutex的实例创建互斥元,调用成员函数lock()来锁定它,调用成员函数unlock()来解锁它。
然而,直接调用成员函数是不推荐的做法,因为这意味着你必须记住在离开函数的每条代码路径上都调用unlock(),包括由于异常所导致的在内。
作为替代,标准C++库提供了std::lock_guard类模板,实现了互斥元的RAII惯用语法;它在构造时锁定所给的互斥元在析构时将互斥元解锁,从而保证被锁定的互斥元始终被正确解锁。

案例2的优化

#include <iostream>
#include <mutex>
# include<thread>
using namespace std;
mutex mtx; // mutex for critical section

int a = 0;
void print_global_var(){
	
	for(int i=0; i<20; i++)
	{
		lock_guard<mutex> guard(mtx);//在构造guard对象时锁定所给的互斥元,在析构guard对象时将互斥元解锁
		//mtx.lock();//加锁

		thread::id tid = this_thread::get_id();
		a++;
		cout << "tid:" << tid << " a:" << a << endl;

		//mtx.unlock();//解锁
	}
	
}

int main(int argc, char *argv[])
{	
	std::thread th1(print_global_var);
	std::thread th2(print_global_var);

	th1.join();
	th2.join();

	return 0;
}

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值