互斥锁
成员方法:lock(), try_lock(), unlock()
1 2
| std::mutex mutex std::shared_mutex mutex
|
1 2 3 4 5 6 7 8 9
| myMutex.lock();
myMutex.unlock();
if (std::try_lock(lock1, lock2) == std::defer_lock) { }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include <iostream> #include <thread> #include <mutex>
std::mutex g_mutex;
void critical_section(int thread_id) { g_mutex.lock(); std::cout << "Thread " << thread_id << " enter critical section." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(5)); g_mutex.unlock(); } int main() { std::thread t1(critical_section, 1); std::thread t2(critical_section, 2); t1.join(); t2.join(); return 0; }
|
lock_guard
建议使用 lock_guard 替代直接使用 mutext.lock()
、mutext.unlock()
,lock_guard
会在构造方法里 mutext.lock()
,析构方法里 mutext.unlock()
,主要为了避免中途异常退出导致 mutext
没有 unlock
,出了作用域后自动调用 lock_guard
的析构方法
unique_lock
lock_guard 只能在析构的时候解锁,不提供 unlock
接口,不够方便,unique_lock
提供 lock
和 unlock
接口,更灵活,虽然 unique_lock
比 lock_guard
灵活很多,但是效率上差一点,内存占用多一点。
递归锁
C++ 中的递归互斥量是一种特殊的互斥量,它可以被同一个线程多次锁定,而不会发生死锁。递归互斥量的实现原理是,在锁定时维护一个锁定计数器,每次解锁时将计数器减一,只有当计数器为 0 时才会释放锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <iostream> #include <thread> #include <mutex> std::recursive_mutex mtx; void foo(int n) { mtx.lock(); std::cout << "Thread " << n << " locked the mutex." << std::endl; if (n > 1) { foo(n - 1); } std::cout << "Thread " << n << " unlocked the mutex." << std::endl; mtx.unlock(); } int main() { std::thread t1(foo, 3); std::thread t2(foo, 2); t1.join(); t2.join(); return 0; }
|
条件锁
成员方法:wait、wait_for、notify_one、notify_all
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| #include <iostream> #include <thread> #include <chrono> #include <queue> #include <mutex> #include <condition_variable> std::queue<int> data_queue; std::mutex data_mutex; std::condition_variable data_cond;
void producer() { for (int i = 1; i <= 10; ++i) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::unique_lock<std::mutex> lock(data_mutex); data_queue.push(i); std::cout << "Producer thread: produce data " << i << std::endl; data_cond.notify_one(); } }
void consumer() { while (true) { std::unique_lock<std::mutex> lock(data_mutex); data_cond.wait(lock, [] { return !data_queue.empty(); }); int data = data_queue.front(); data_queue.pop(); std::cout << "Consumer thread: consume data " << data << std::endl; if (data == 10) { break; } } } int main() { std::thread t1(producer); std::thread t2(consumer); t1.join(); t2.join(); return 0; }
|
读写锁
成员方法:lock(), unlock(), lock_shared, unlock_shared
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| #include <iostream> #include <shared_mutex> #include <thread>
std::shared_mutex sharedMtx; int sharedData = 0;
void readData() { sharedMtx.lock_shared(); std::cout << "Read shared data: " << sharedData << std::endl; sharedMtx.unlock_shared(); }
void writeData() { sharedMtx.lock(); sharedData++; std::cout << "Write shared data: " << sharedData << std::endl; sharedMtx.unlock(); }
int main() { std::thread readerThread1(readData); std::thread readerThread2(readData); std::thread writerThread(writeData);
readerThread1.join(); readerThread2.join(); writerThread.join();
return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| #include <iostream> #include <thread> #include <chrono> #include <shared_mutex> std::shared_mutex rw_lock; int shared_var = 0;
void writer() { for (int i = 0; i < 10; ++i) { std::unique_lock<std::shared_mutex> lock(rw_lock); ++shared_var; std::cout << "Writer thread: write shared_var=" << shared_var << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } }
void reader(int id) { for (int i = 0; i < 10; ++i) { std::shared_lock<std::shared_mutex> lock(rw_lock); int value = shared_var; std::cout << "Reader thread " << id << ": read shared_var=" << value << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } int main() { std::thread t1(writer); std::thread t2(reader, 1); std::thread t3(reader, 2); std::thread t4(reader, 3); t1.join(); t2.join(); t3.join(); t4.join(); return 0; }
|