#include <iostream> #include <thread> #include <Windows.h> static CRITICAL_SECTION g_winsec; void print_block (int n, char c) { EnterCriticalSection(&g_winsec); // 2. 進入臨界區 for (int i=0; i<n; ++i) { std::cout << c; } std::cout << '\n'; LeaveCriticalSection(&g_winsec); // 3. 離開臨界區 } int main () { InitializeCriticalSection(&g_winsec); // 1. 初始化臨界資源對象 std::thread th1 (print_block,50,'*'); std::thread th2 (print_block,50,'$'); th1.join(); th2.join(); return 0; }
輸出:ios
************************************************** $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
測試1:window 臨界區ide
#include <iostream> #include <thread> #include <Windows.h> static CRITICAL_SECTION g_winsec; void print_block (int n, char c) { EnterCriticalSection(&g_winsec); // 2. 進入臨界區 EnterCriticalSection(&g_winsec); // 屢次進入 。。。 EnterCriticalSection(&g_winsec); // 屢次進入 。。。 for (int i=0; i<n; ++i) { std::cout << c; } std::cout << '\n'; LeaveCriticalSection(&g_winsec); // 3. 離開臨界區 LeaveCriticalSection(&g_winsec); // 屢次離開 。。。 LeaveCriticalSection(&g_winsec); // 屢次離開 。。。 } int main () { InitializeCriticalSection(&g_winsec); // 1. 初始化臨界資源對象 std::thread th1 (print_block,50,'*'); std::thread th2 (print_block,50,'$'); th1.join(); th2.join(); return 0; }
輸出:[結果正確]函數
************************************************** $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
測試2:std::mutex測試
// mutex example #include <iostream> // std::cout #include <thread> // std::thread #include <mutex> // std::mutex std::mutex mtx; // mutex for critical section void print_block (int n, char c) { // critical section (exclusive access to std::cout signaled by locking mtx): mtx.lock(); mtx.lock(); mtx.lock(); for (int i=0; i<n; ++i) { std::cout << c; } std::cout << '\n'; mtx.unlock(); mtx.unlock(); mtx.unlock(); } int main () { std::thread th1 (print_block,50,'*'); std::thread th2 (print_block,50,'$'); th1.join(); th2.join(); return 0; }
輸出:優化
程序異常退出
#include <iostream> #include <thread> #include <Windows.h> static CRITICAL_SECTION g_winsec; class CWinLock { public: CWinLock(CRITICAL_SECTION *winsec) : m_winsec(winsec) { EnterCriticalSection(m_winsec); // 進入臨界區 } ~CWinLock() { LeaveCriticalSection(m_winsec); // 離開臨界區 } private: CRITICAL_SECTION *m_winsec = nullptr; }; void print_block (int n, char c) { CWinLock win_lock(&g_winsec); for (int i=0; i<n; ++i) { std::cout << c; } std::cout << '\n'; } int main () { InitializeCriticalSection(&g_winsec); // 1. 初始化臨界資源對象 std::thread th1 (print_block,50,'*'); std::thread th2 (print_block,50,'$'); th1.join(); th2.join(); return 0; }
輸出:ui
************************************************** $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
try_lock | 若是沒有被其它線程鎖定,則鎖定互斥鎖 |
unlock | 解鎖互斥鎖 |
測試:僅演示說明,使用 recursive_mutex 時需考慮是否存在優化空間!this
#include <iostream> #include <thread> #include <mutex> std::recursive_mutex mtx; void print_block (int n, char c) { mtx.lock(); mtx.lock(); mtx.lock(); for (int i=0; i<n; ++i) { std::cout << c; } std::cout << '\n'; mtx.unlock(); mtx.unlock(); mtx.unlock(); } int main () { std::thread th1 (print_block,50,'*'); std::thread th2 (print_block,50,'$'); th1.join(); th2.join(); return 0; }
輸出:spa
************************************************** $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
lock | 調用線程將鎖定timed_mutex,並在必要時進行阻塞(其行爲與 mutex 徹底相同) |
try_lock | 嘗試鎖定 timed_mutex,而不進行阻塞(其行爲與互斥鎖徹底相同) |
try_lock_for | 嘗試鎖定 timed_mutex, 最多阻塞 rel_time 時間 |
try_lock_until | 嘗試鎖定 timed_mutex,最多阻塞到 abs_time 時間點 |
unlock | 解鎖 timed_mutex,釋放對其的全部權(其行爲與 mutex 相同) |
測試1: try_lock_for線程
// timed_mutex::try_lock_for example #include <iostream> // std::cout #include <chrono> // std::chrono::milliseconds #include <thread> // std::thread #include <mutex> // std::timed_mutex std::timed_mutex mtx; void fireworks () { // waiting to get a lock: each thread prints "-" every 200ms: while (!mtx.try_lock_for(std::chrono::milliseconds(200))) { std::cout << "-"; } // got a lock! - wait for 1s, then this thread prints "*" std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::cout << "*\n"; mtx.unlock(); } int main () { std::thread threads[10]; // spawn 10 threads: for (int i=0; i<10; ++i) threads[i] = std::thread(fireworks); for (auto& th : threads) th.join(); return 0; }
輸出:code
------------------------------------* ----------------------------------------* -----------------------------------* ------------------------* -------------------------* --------------------* ---------------* --------* -----* *
測試2:try_lock_until
// timed_mutex::try_lock_until example #include <iostream> // std::cout #include <chrono> // std::chrono::system_clock #include <thread> // std::thread #include <mutex> // std::timed_mutex #include <ctime> // std::time_t, std::tm, std::localtime, std::mktime std::timed_mutex cinderella; // gets time_point for next midnight: std::chrono::time_point<std::chrono::system_clock> midnight() { using std::chrono::system_clock; std::time_t tt = system_clock::to_time_t (system_clock::now()); struct std::tm * ptm = std::localtime(&tt); ++ptm->tm_mday; ptm->tm_hour=0; ptm->tm_min=0; ptm->tm_sec=0; return system_clock::from_time_t (mktime(ptm)); } void carriage() { if (cinderella.try_lock_until(midnight())) { std::cout << "ride back home on carriage\n"; cinderella.unlock(); } else std::cout << "carriage reverts to pumpkin\n"; } void ball() { cinderella.lock(); std::cout << "at the ball...\n"; cinderella.unlock(); } int main () { std::thread th1 (ball); std::thread th2 (carriage); th1.join(); th2.join(); return 0; }
輸出:
at the ball... ride back home on carriage