熱線電話:0755-23712116
郵箱:contact@shuangyi-tech.com
地址:深圳市寶安區(qū)沙井街道后亭茅洲山工業(yè)園工業(yè)大廈全至科技創(chuàng)新園科創(chuàng)大廈2層2A
今天和大家說說C++多線程中的原子操作。首先為什么會(huì)有原子操作呢?這純粹就是C++這門語言的特性所決定的,C++這門語言是為性能而生的,它對性能的追求是沒有極限的,它總是想盡一切辦法提高性能。互斥鎖是可以實(shí)現(xiàn)數(shù)據(jù)的同步,但同時(shí)是以犧牲性能為代價(jià)的。口說無憑,我們做個(gè)實(shí)驗(yàn)就知道了。
我們將一個(gè)數(shù)加一再減一,循環(huán)一定的次數(shù),開啟20個(gè)線程來觀察,這個(gè)正確的結(jié)果應(yīng)該是等于0的。
首先是不加任何互斥鎖同步
#include <iostream>
#include <thread>
#include <atomic>
#include <time.h>
#include <mutex>
using namespace std;
#define MAX 100000
#define THREAD_COUNT 20
int total = 0;
void thread_task()
{
for (int i = 0; i < MAX; i++)
{
total += 1;
total -= 1;
}
}
int main()
{
clock_t start = clock();
thread t[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; ++i)
{
t[i] = thread(thread_task);
}
for (int i = 0; i < THREAD_COUNT; ++i)
{
t[i].join();
}
clock_t finish = clock();
cout << "result:" << total << endl;
cout << "duration:" << finish - start << "ms" << endl;
return 0;
}
以上程序運(yùn)行時(shí)相關(guān)快的,但是結(jié)果卻是不正確的。
那么我們將線程加上互斥鎖mutex再來看看。
#include <iostream>
#include <thread>
#include <atomic>
#include <time.h>
#include <mutex>
using namespace std;
#define MAX 100000
#define THREAD_COUNT 20
int total = 0;
mutex mt;
void thread_task()
{
for (int i = 0; i < MAX; i++)
{
mt.lock();
total += 1;
total -= 1;
mt.unlock();
}
}
int main()
{
clock_t start = clock();
thread t[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; ++i)
{
t[i] = thread(thread_task);
}
for (int i = 0; i < THREAD_COUNT; ++i)
{
t[i].join();
}
clock_t finish = clock();
// 輸出結(jié)果
cout << "result:" << total << endl;
cout << "duration:" << finish - start << "ms" << endl;
return 0;
}
我們可以看到運(yùn)行結(jié)果是正確的,但是時(shí)間比原來慢太多了。雖然很無奈,但這也是沒有辦法的,因?yàn)橹挥性诒WC準(zhǔn)確的前提才能去追求性能。
那有沒有什么辦法在保證準(zhǔn)確的同時(shí),又能提高性能呢?
原子操作就橫空出世了!
定義原子操作的時(shí)候必須引入頭文件
#include <atomic>
那么如何利用原子操作提交計(jì)算的性能呢?實(shí)際上很簡單的。
#include <iostream>
#include <thread>
#include <atomic>
#include <time.h>
#include <mutex>
using namespace std;
#define MAX 100000
#define THREAD_COUNT 20
//原子操作
atomic_int total(0);
void thread_task()
{
for (int i = 0; i < MAX; i++)
{
total += 1;
total -= 1;
}
}
int main()
{
clock_t start = clock();
thread t[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; ++i)
{
t[i] = thread(thread_task);
}
for (int i = 0; i < THREAD_COUNT; ++i)
{
t[i].join();
}
clock_t finish = clock();
// 輸出結(jié)果
cout << "result:" << total << endl;
cout << "duration:" << finish - start << "ms" << endl;
return 0;
}
可以看到,我們在這里只需要定義atomic_int total(0)就可以實(shí)現(xiàn)原子操作了,就不需要互斥鎖了。而性能的提升也是非常明顯的,這就是原子操作的魅力所在。