由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;
}


被折叠的 条评论
为什么被折叠?



