C++ —— 線程同步(互斥鎖)
- 線程同步
- 互斥鎖(互斥量)
- 測試代碼
- mutex互斥鎖
線程同步
線程同步
:多線程協同工作,協商如何使用共享資源。
C++11
線程同步包含三部分內容:
互斥鎖
(互斥量)- 條件變量
- 生產/消費者模型
互斥鎖(互斥量)
只有加鎖
和解鎖
兩種狀態,確保同一時間
只有一個線程
訪問共享資源。
訪問共享資源之前加鎖
,加鎖成功
,訪問
資源,訪問完成
,解鎖
釋放。
若某線程持有鎖
,其他線程形成等待隊列
。
C++11
提供了4
種互斥鎖:
mutex
:互斥鎖(最常用)timed_mutex
:帶超時機制的互斥鎖recursive_mutex
:遞歸互斥鎖recursive_timed_mutex
:帶超時機制的遞歸互斥鎖
測試代碼
#include <iostream>
#include <thread>
using namespace std;void func (int n, const string& s) {for (int i = 1; i <= 10; i++) {cout << "No." << i << ", n = " << n << ", s = " << s << endl;this_thread::sleep_for(chrono::seconds(1));}
}
a
int main () {thread t1(func, 1, "t1");thread t2(func, 2, "t2");thread t3(func, 3, "t3");thread t4(func, 4, "t4");thread t5(func, 5, "t5");thread t6(func, 6, "t6");t1.join();t2.join();t3.join();t4.join();t5.join();t6.join();return 0;
}
cout
屬于全局對象,若多線程都用它向屏幕輸出文字,會出亂子。線程越多,越容易亂。
mutex互斥鎖
使用互斥鎖
給cout
加鎖,代碼如下:
#include <iostream>
#include <thread>
#include <mutex> // 使用互斥鎖需要包含的頭文件
using namespace std;mutex mtx; // 創建互斥鎖對象,用于保護共享資源cout對象。void func (int n, const string& s) {for (int i = 1; i <= 10; i++) {// 每次調用cout對象之前,申請加鎖mtx.lock();cout << "No." << i << ", n = " << n << ", s = " << s << endl;// 用完了就解鎖mtx.unlock();this_thread::sleep_for(chrono::seconds(1));}
}int main () {// 代碼不變...
}
再看一段示例代碼:
#include <iostream>
#include <chrono> // 時間相關操作的頭文件
#include <thread> // 線程相關操作的頭文件
#include <mutex> // 互斥鎖的頭文件
using namespace std;int a = 0;
mutex mtx; // 創建互斥鎖對象,用于保護共享資源a變量。void func () {for (int i = 0; i < 1000000; ++i) {mtx.lock();a++;mtx.unlock();}
}int main () {auto start = chrono::steady_clock::now();thread t1(func);thread t2(func);t1.join();t2.join();auto end = chrono::steady_clock::now();cout << "time = " << chrono::duration_cast<chrono::milliseconds>(end - start).count() << "ms" << endl;cout << "a = " << a << endl;return 0;
}
運行結果:
time = 101ms
a = 2000000
在代碼中添加一些打印信息,能更清楚的觀察到:兩個線程申請加鎖,只有一個成功,另外一個線程等待,直到第一個線程解鎖后第二個線程才能加鎖。
#include <iostream>
#include <chrono> // 時間相關操作的頭文件
#include <thread> // 線程相關操作的頭文件
#include <mutex> // 互斥鎖的頭文件
using namespace std;int a = 0;
mutex mtx;void func () {for (int i = 0; i < 1000000; ++i) {cout << "thread id: " << this_thread::get_id() << ", 申請加鎖" << endl;mtx.lock();cout << "thread id: " << this_thread::get_id() << ", 加鎖成功" << endl;a++;this_thread::sleep_for(chrono::seconds(5));mtx.unlock();cout << "thread id: " << this_thread::get_id() << ", 解鎖" << endl;this_thread::sleep_for(chrono::seconds(1));}
}int main () {thread t1(func);thread t2(func);t1.join();t2.join();cout << "a = " << a << endl;return 0;
}
運行結果:
thread id: 139727756003072, 申請加鎖
thread id: 139727756003072, 加鎖成功
thread id: 139727747610368, 申請加鎖
thread id: 139727756003072, 解鎖
thread id: 139727747610368, 加鎖成功
thread id: 139727756003072, 申請加鎖
thread id: 139727747610368, 解鎖
…
感謝瀏覽