1. 死鎖與解鎖:ios
#include <iostream> #include <thread> #include <mutex> using namespace std; //thread引用類型函數,模板,避免類型轉換,儘可能指針,引用 //鎖住一個變量以後,儘快操做完解鎖,不要再鎖,不然互鎖 #define COUNT 100000 mutex g_mutex1, g_mutex2;//互斥量 void add1(int *p1, int *p2) { for (int i = 0; i < COUNT; i++) { /*g_mutex1.lock(); p1++; g_mutex2.lock(); p2++; g_mutex1.unlock(); g_mutex2.unlock();*/ g_mutex1.lock(); (*p1)++; g_mutex1.unlock(); g_mutex2.lock(); (*p2)++; g_mutex2.unlock(); } } void add2(int *p1, int *p2) { for (int i = 0; i < COUNT; i++) { /*g_mutex2.lock(); g_mutex1.lock(); p1++; g_mutex1.unlock(); p2++; g_mutex2.unlock();*/ g_mutex2.lock(); (*p2)++; g_mutex2.unlock(); g_mutex1.lock(); (*p1)++; g_mutex1.unlock(); } } void main() { int a = 0; int b = 0; thread th1(add1, &a, &b); thread th2(add2, &a, &b); th1.join(); th2.join(); while (1) { cout << a << endl; cout << b << endl; this_thread::sleep_for(chrono::seconds(1)); } cin.get(); }
2. 迅雷面試題:面試
編寫一個程序,開啓3個線程,這3個線程的ID分別爲A、B、C,每一個線程將本身的ID在屏幕上打印10遍,多線程
要求輸出結果必須按ABC的順序顯示。如:ABCABC...,依次遞推。函數
【參考答案】this
//編寫一個程序,開啓3個線程,這3個線程的ID分別爲A、B、C,每一個線程將本身的ID在屏幕上打印10遍, //要求輸出結果必須按ABC的順序顯示。如:ABCABC...,依次遞推。 #include <iostream> #include <thread> #include <mutex> #include <condition_variable> using namespace std; int LOOP = 10; //循環次數 int flag = 0; //標識符 012012012012 mutex m; condition_variable cv; void fun(int id) { for (int i = 0; i < LOOP; i++) { unique_lock<mutex> ulk(m); //設定鎖定 while ((id-65) != flag) { cv.wait(ulk); //不是該出現的場合,就等待 } cout << (char)id; //轉換id flag = (flag + 1) % 3; //012,012,012,... cv.notify_all(); //通知所有 } } void main() { thread t1(fun, 65); thread t2(fun, 66); thread t3(fun, 67); t1.join(); t2.join(); t3.join(); cin.get(); }
運行結果:spa
【分析】若題目變爲:4個線程,輸出結果要求爲: ABCDABCDABCD...又該如何作呢?線程
//編寫一個程序,開啓3個線程,這3個線程的ID分別爲A、B、C,每一個線程將本身的ID在屏幕上打印10遍, //要求輸出結果必須按ABC的順序顯示。如:ABCABC...,依次遞推。 #include <iostream> #include <thread> #include <mutex> #include <condition_variable> using namespace std; int LOOP = 10; //循環次數 int flag = 0; //標識符 012012012012 mutex m; condition_variable cv; void fun(int id) { for (int i = 0; i < LOOP; i++) { unique_lock<mutex> ulk(m); //設定鎖定 while ((id-65) != flag) { cv.wait(ulk); //不是該出現的場合,就等待 } cout << (char)id; //轉換id flag = (flag + 1) % 4; //012,012,012,... cv.notify_all(); //通知所有 } } void main() { thread t1(fun, 65); thread t2(fun, 66); thread t3(fun, 67); thread t4(fun, 68); t1.join(); t2.join(); t3.join(); t4.join(); cin.get(); }
運行結果:指針
3. 思考:上題中若變爲開啓5個線程,ID分別爲1,2,3,4,5,每一個線程將本身的ID在屏幕上打印10遍,要求輸出結果爲:12345,54321,12345,54321,...依此類推。code
4. 線程交換 swap:blog
#include <iostream> #include <thread> using namespace std; void main() { thread t1([]() {cout << "ZhangShan"<<endl; }); thread t2([]() {cout << "LiSi"<<endl; }); cout << "t1.get_id():" << t1.get_id() << " t2.get_id():" << t2.get_id() << endl; swap(t1, t2); //交換句柄 cout << "t1.get_id():" << t1.get_id() << " t2.get_id():" << t2.get_id() << endl; t1.join(); t2.join(); cin.get(); }
5. 線程移動 move:
#include <iostream> #include <thread> #include <cstdlib> using namespace std; void main() { thread t1([]() { int i = 0; while (1) { i++; if (i > 1000000000) { break; } } cout << i << endl; system("pause"); }); cout << "t1:" << t1.get_id() << endl; //6872 //t1.join(); thread t2 = move(t1);//線程移動,t2具有了t1的屬性,t1掛了 cout << "t1:" << t1.get_id() << endl; //0 cout << "t2:" << t2.get_id() << endl; //6872 t2.join(); cin.get(); }
運行結果:
6. 線程自動加解鎖:
#include <iostream> #include <thread> #include <mutex> using namespace std; #define N 10000000 mutex g_mutex;//全局互斥量 void add(int *p) { for (int i = 0; i < N; i++) { unique_lock<mutex> ulk(g_mutex); //沒有mutex全部權,自動加鎖自動解鎖,根據塊語句鎖定 //根據mutex屬性來決定,是否能夠加鎖 //lock_guard<mutex> lgd(g_mutex); //擁有mutex全部權,自動加鎖自動解鎖 //讀取mutex失敗的狀況下就會一直等待 (*p)++; } } void main() { int a = 0; thread t1(add, &a); thread t2(add, &a); t1.join(); t2.join(); cout << a << endl; cin.get(); }
7. 線程等待固定時間:
#include <iostream> #include <thread> #include <chrono> #include <mutex> #include <condition_variable> #include <cstdlib> #include <ctime> using namespace std; condition_variable cv; mutex m; bool done=false; void run() { auto start = chrono::high_resolution_clock::now(); //當前時間 auto end = start + chrono::seconds(3); unique_lock<mutex> ulk(m); while (!done) { if (cv.wait_until(ulk, end) == cv_status::timeout)//超時 { done = true; break; } } //this_thread::sleep_until(end); system("pause"); } void main1601() { thread th(run); cin.get(); } void main() { time_t t1, t2; auto start = chrono::high_resolution_clock::now(); //當前時間 t1 = time(&t1); double db = 0; for (int i = 0; i < 1000000000; i++) { db += i; } auto end = chrono::high_resolution_clock::now(); //當前時間 t2 = time(&t2); cout << (end - start).count() << endl; //10^-9秒(ns) cout << difftime(t2, t1) << endl; cin.get(); }
8. 多線程實現生產者、消費者:
#include <iostream> #include <thread> #include <mutex> #include <condition_variable> #include <array> #include <vector> using namespace std; mutex m; condition_variable isfull, isempty;//處理兩種狀況 bool flag = true;//標誌,消費完了就退出 vector<int> myint(10);//開闢10個元素 void produce(int num) //生產 { for (int i = 0; i < num; i++) { unique_lock<mutex> lk(m); //鎖定 while (myint.size()>=10) { isempty.wait(lk); //滿了一直等待 } myint.push_back(i);//插入 cout << "生產" << i << endl; isfull.notify_all();//通知消費者 } this_thread::sleep_for(chrono::seconds(5));//休眠5秒 flag = false; } void consume() //消費 { while (flag) { unique_lock<mutex> lk(m); //鎖定 while (myint.size()==0) { isfull.wait(lk);//等待 } if (flag) { cout << "消費" << myint[myint.size() - 1] << " " << this_thread::get_id() << endl; myint.pop_back();//剔除最後一個 isempty.notify_all();//通知生產者繼續生產 } } } void main() { thread t1(consume); //消費者 thread t2(consume); thread t3(consume); //produce(100); thread s1(produce,15);//消費者 thread s2(produce,15); t1.join(); t2.join(); t3.join(); cin.get(); }