C++ 线程锁 mutex 理解 附代码
1. 概述
对C++
里面的mutex
相关知识进行梳理,理解线程锁
。
2. 理解
mutex英文含义如下,表示一种不相容的性质。
mutex
n. 互斥;互斥元,互斥体;互斥量
- C++里面的mutex类是用来进行
线程同步
,保护数据
的,防止不同线程对同一数据同时进行处理
。如果不使用线程锁会使程序不稳定,达不到预期的效果。 - 它实际上是用来
对线程进行处理的,不是直接处理数据
。不同的线程只有拿到了线程锁才可以继续运行
,否则需要等待其他线程解除线程锁。 - 线程进行同步时需要进行线程锁的
加锁
、解锁
的操作。如果加锁之后没有及时解锁
可能会导致死锁
现象。因为其他线程会等待其他线程解除线程锁,如果一直等不到,可能会一直处于阻塞
的状态。
boost中的锁有
class mutex
typedef mutex try_mutex;
class timed_mutex
typedef unique_lock<mutex> scoped_lock;
typedef detail::try_lock_wrapper<mutex> scoped_try_lock;
typedef unique_lock<timed_mutex> scoped_timed_lock;
typedef detail::try_lock_wrapper<timed_mutex> scoped_try_lock;
typedef scoped_timed_lock scoped_lock;
3. boost::mutex
C++使用线程锁时最简单的就是使用boost::mutex。
3.1 无锁
如果不使用线程锁
,代码示例如下
使用命令
g++ nomutextest.cpp -o nomutex -lboost_system -lboost_thread
#include <boost/thread/thread.hpp>
#include <iostream>
#include <iomanip>
#include <unistd.h>
/*
* g++ nomutextest.cpp -o nomutex -lboost_system -lboost_thread
*/
int num = 5;
void helloA()
{
std::cout << "****I'm thread A ! " << boost::this_thread::get_id() << " --- Start " << std::endl;
std::cout << "****I'm thread A the num is "<<num <<std::endl;
num++;
std::cout << "****I'm thread A the num+1 is "<<num <<std::endl;
num++;
std::cout << "****I'm thread A the num+1+1 is "<<num <<std::endl;
sleep(1);
std::cout << "****I'm thread A ! --- OVER " << std::endl;
}
void helloB()
{
std::cout << "I'm thread B ! " << boost::this_thread::get_id() << " --- Start " << std::endl;
std::cout << "I'm thread B the num is "<<num <<std::endl;
num--;
std::cout << "I'm thread B the num-1 is "<<num <<std::endl;
num--;
std::cout << "I'm thread B the num-1-1 is "<<num <<std::endl;
std::cout << "I'm thread B ! --- OVER " << std::endl;
}
int main(int argc, char* argv[])
{
// 建立并执行两个线程
boost::thread thrdA(&helloA);
boost::thread thrdB(&helloB);
thrdA.join(); // 等待子线程完成后再继续执行主进程;
thrdB.join();
// 等待两个 join 后才会继续执行
std::cout<< " ==== over ==== "<<std::endl;
return 0;
}
由于线程实际运行时对num处理的先后顺序不一样导致结果不一样。
可能thrdA先对num进行加处理,
可以允许
也有可能thrdB先对num进行减处理,
可以允许
也有可能thrdA、thrdB对num同时进行处理
。禁止这种情况
输出结果可能为下面情况
线程A先对num进行处理
A5 -> A6 -> A7->B7 -> B6 -> B5
****I'm thread A ! 7f01551c6700 --- Start I'm thread B !
****I'm thread A the num is 5
****I'm thread A the num+1 is 6
****I'm thread A the num+1+1 is 7
7f01549c5700 --- Start
I'm thread B the num is 7
I'm thread B the num-1 is 6
I'm thread B the num-1-1 is 5
I'm thread B ! --- OVER
****I'm thread A ! --- OVER
==== over ====
或者
线程B先对num进行处理,
B5 -> B4 -> B3 -> A3 -> A4 -> A5
I'm thread B ! 7ff008235700 --- Start
I'm thread B the num is 5
I'm thread B the num-1 is 4
I'm thread B the num-1-1 is 3
I'm thread B ! --- OVER
****I'm thread A ! 7ff008a36700 --- Start
****I'm thread A the num is 3
****I'm thread A the num+1 is 4
****I'm thread A the num+1+1 is 5
****I'm thread A ! --- OVER
==== over ====
或者
线程A、B同时对num进行处理。
A5 -> A6 -> B6 -> B5 -> B4 -> A5
****I'm thread A ! I'm thread B ! 7f1c044567007f1c04c57700 --- Start --- Start
****I'm thread A the num is 5
****I'm thread A the num+1 is
I'm thread B the num is 6
I'm thread B the num-1 is 5
6I'm thread B the num-1-1 is 4
I'm thread B ! --- OVER
****I'm thread A the num+1+1