window 临界区
- window 临界区资源对象与C++的 std::mutex 对象相似,能够爱护多个线程对临界区资源的拜访。
#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;}
输入:
**************************************************$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
屡次进入临界区试验
- window 临界资源对象能够在同一线程中多次重复进入,对应次数的来到,程序仍失常执行。
- std::mutex 对象只能在同一线程进行一次加锁并对应一次解锁,否则程序抛出异样。
测试1:window 临界区
#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::mutexstd::mutex mtx; // mutex for critical sectionvoid 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;}
输入:
程序异样退出
主动析构技术
- RAII(Resource Acquisition Is Initialization),也称为“资源获取就是初始化”,是C++语言的一种治理资源、防止透露的习用法。
- C++规范保障任何状况下,已结构的对象最终会销毁,即它的析构函数最终会被调用。简略的说,RAII 的做法是应用一个对象,在其结构时获取资源,在对象生命期管制对资源的拜访使之始终保持无效,最初在对象析构的时候开释资源。
#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;}
输入:
**************************************************$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
std::recursive_mutex
- 就像互斥锁(mutex)一样,递归互斥锁(recursive_mutex)是可锁定的对象,但它容许同一线程取得对互斥锁对象的多级所有权(屡次lock)。
- 这容许从曾经锁定它的线程锁定(或尝试锁定)互斥对象,从而取得对互斥对象的新所有权级别:互斥对象实际上将放弃对该线程的锁定,直到调用其成员 unlock 的次数与此所有权级别的次数雷同。
try_lock | 如果没有被其它线程锁定,则锁定互斥锁 |
unlock | 解锁互斥锁 |
测试:仅演示阐明,应用 recursive_mutex 时需思考是否存在优化空间!
#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;}
输入:
**************************************************$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
std::timed_mutex、std::recursive_timed_mutex
std::timed_mutex
- 定时互斥锁是一个可工夫锁定的对象,旨在告诉何时要害代码须要独占拜访,就像惯例互斥锁一样,但还反对定时尝试锁定申请。
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_mutexstd::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;}
输入:
------------------------------------*----------------------------------------*-----------------------------------*------------------------*-------------------------*--------------------*---------------*--------*-----**
测试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::mktimestd::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
std::recursive_timed_mutex
- 递归定时互斥锁将 recursive_timed 和 timed_mutex 的性能联合到一个类中:它既反对通过单个线程获取多个锁定级别又反对定时的 try_lock 申请。
- 成员函数与 timed_mutex 雷同。