一、概述
多线程修改基本数据类型时,也可能出现同步问题,哪怕时最简单的累加操作。通过mutex在对同一个数据操作时加锁,实现了对资源的独占。
二、代码示例
#pragma once
#include <mutex>
#include <thread>
#include <iostream>
#include <stdio.h>
using namespace std;
class MutexTest
{
private:
static mutex _mutex;
static int _val1;
static int _val2;
public:
static void DoOne()
{
for (int i = 0; i < 10000000; i++)
{
_val2++;
}
printf("thread %d value: %d\n",this_thread::get_id(), _val2); //cout也是线程不安全,不能保证整个cout不被其他线程终端
_mutex.lock();
for (int i = 0; i < 10000000; i++)
{
_val1++;
}
printf("thread %d mutexValue: %d\n", this_thread::get_id(), _val1); //cout也是线程不安全,不能保证整个cout不被其他线程终端
_mutex.unlock();
}
void DoTest()
{
thread thread1(DoOne);
thread thread2(DoOne);
thread1.join();
thread2.join();
}
};
mutex MutexTest::_mutex;
int MutexTest::_val1=0;
int MutexTest::_val2=0;
三、输出
thread 16640 value: 9612465
thread 16516 value: 10343307
thread 16640 mutexValue: 10000000
thread 16516 mutexValue: 20000000
四、分析
不加互斥量访问,会导致实际累加的结果不是我们期望的最终结果20000000,而只有10343307。原因在于++操作不是一个原子操作。
++操作其实包含以下三步
register1 = _val2
register1 = register1+1
_val2 = register1
多线程访问时,可能出现以下情况
register1=_val2
reigster2=_val2
resigter1=_val2+1
register2=_val2+1
_val2=register1
_val2=register2
这种情况下,实际会少加1,所以才会有代码输出的现象,结果小于2000000,甚至很接近10000000。