一.简介
这里以mutex锁机制为例.
mutex函数:是一套专门用于线程同步锁机制的函数.
#include <mutex>
using namespace std;
atomic原子操作:是在新标准C++11,引入了原子操作的概念,并通过这个新的头文件提供了多种原子操作数据类型,例如,atomic_bool,atomic_int等等.
#include <atomic>
using namespace std;
二.效率对比
#include <iostream>
#include <thread>
#include <mutex>
#include <atomic>
#include <time.h>
#define TEST_DATA_LENGTH 100000 //每个线程操作次数
#define THREAD_NUM 10 //线程个数
using namespace std;//引入std命名空间
mutex m;//声明互斥锁m
long n_total = 0;
long m_total = 0;
atomic<long> a_total = 0;//原子量的初始化
//在不采用互斥锁和原子类的情况下
void test_f_normal()
{
for(int i = 0; i < TEST_DATA_LENGTH; i++)
{
n_total += 1;
}
}
//使用mutex互斥锁
void test_f_mutex()
{
for(int i = 0; i < TEST_DATA_LENGTH; i++)
{
m.lock();
m_total += 1;
m.unlock();
}
}
//使用原子操作
void test_f_atomic()
{
for(int i = 0; i < TEST_DATA_LENGTH; i++)
{
a_total += 1;
}
}
void main()
{
thread ts[THREAD_NUM];
//normal mode ,result is error
clock_t start = clock();
for(int i = 0; i < THREAD_NUM; i++)
{
ts[i] = thread(&test_f_normal);
}
for(int i = 0; i < THREAD_NUM; i++)
{
ts[i].join();
}
clock_t end = clock();
cout << "total: " << n_total << endl;
cout << "test_f_normal: " << end - start << endl;
//use mutex ,
clock_t mstart = clock();
for(int i = 0; i < THREAD_NUM; i++)
{
ts[i] = thread(&test_f_mutex);
}
for(int i = 0; i < THREAD_NUM; i++)
{
ts[i].join();
}
clock_t mend = clock();
cout << "total: " << m_total << endl;
cout << "test_f_mutex: " << mend - mstart << endl;
//use atomic
clock_t astart = clock();
for(int i = 0; i < THREAD_NUM; i++)
{
ts[i] = thread(&test_f_atomic);
}
for(int i = 0; i < THREAD_NUM; i++)
{
ts[i].join();
}
clock_t aend = clock();
cout << "total: " << a_total << endl;
cout << "test_f_atomic: " << aend - astart << endl;
system("pause");
return;
}
温馨提示:在运行”test_f_normal: XX”时候可能会卡住
原因是:在使用互斥锁的情况下,效率会慢很多,可以通过设置线程个数/操作次数即可修改.耐心等待.
运行结果:
total: 601409
test_f_normal: 29
total: 1000000
test_f_mutex: 11274
total: 1000000
test_f_atomic: 35
三.总结
由上面的测试结果可以看得出来
1.在不使用互斥锁和原子量的时候,多线程的操作会使结果是错误的.
2.原子操作的实现跟普通数据类型类似,但是它能够在保证结果正确的前提下,提供比mutex等锁机制更好的性能
提示:开发过程中,对于多线程的情况下,单个基础数据类型的数据共享安全,尽量使用原子操作代替锁机制. 当需要对代码块进行数据安全保护的时候,就需要选择使用锁机制了.