鸽了好久, 终于想起来还有个博客主题没写…
1. 基础锁管理器:lock_guard
std::lock_guard
是最基础的 RAII 风格锁管理器,使用简单且安全。
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 <mutex> #include <thread>
std::mutex mtx;
void print_thread_id(int id) { std::lock_guard<std::mutex> lock(mtx); std::cout << "Thread ID: " << id << std::endl; }
int main() { std::thread t1(print_thread_id, 1); std::thread t2(print_thread_id, 2);
t1.join(); t2.join();
return 0; }
|
特点:
- 构造时自动加锁
- 析构时自动解锁
- 不能手动解锁
- 不能复制或移动
2. 灵活的锁管理器:unique_lock
std::unique_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 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 <mutex> #include <thread>
std::mutex mtx;
void print_thread_id(int id) { { std::unique_lock<std::mutex> lock1(mtx, std::defer_lock); lock1.lock(); std::cout << "defer_lock - Thread " << id << std::endl; lock1.unlock(); }
{ std::unique_lock<std::mutex> lock2(mtx, std::try_to_lock); if (lock2.owns_lock()) { std::cout << "try_to_lock succeeded - Thread " << id << std::endl; } else { std::cout << "try_to_lock failed - Thread " << id << std::endl; } }
{ mtx.lock(); std::unique_lock<std::mutex> lock3(mtx, std::adopt_lock); std::cout << "adopt_lock - Thread " << id << std::endl; }
{ std::unique_lock<std::mutex> lock4(mtx); std::cout << "default lock - Thread " << id << std::endl; } }
int main() { std::thread t1(print_thread_id, 1); std::thread t2(print_thread_id, 2);
t1.join(); t2.join();
return 0; }
|
特点:
- 支持手动加锁/解锁
- 可以检查锁状态
- 支持锁的所有权转移
- 比
lock_guard
更灵活但开销略大
3. 超时锁:timed_mutex
std::timed_mutex
支持带超时的锁定操作,适用于需要避免长时间等待的场景。
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 53 54
| #include <chrono> #include <iostream> #include <mutex> #include <thread>
std::timed_mutex mtx;
bool try_lock_with_timeout() { if (mtx.try_lock_for(std::chrono::seconds(2))) { std::cout << "Mutex locked" << std::endl;
mtx.unlock(); return true; } else { std::cout << "Failed to lock mutex within 2 seconds" << std::endl; return false; } }
bool try_lock_until_deadline() { auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(2); if (mtx.try_lock_until(deadline)) { std::cout << "Locked before deadline" << std::endl; mtx.unlock(); return true; } return false; }
int main() { std::thread t1(try_lock_with_timeout); std::thread t2(try_lock_with_timeout);
t1.join(); t2.join();
return 0; }
|
特点:
- 支持
try_lock_for
:指定等待时长
- 支持
try_lock_until
:指定截止时间点
- 避免无限等待
4. 多锁管理:scoped_lock
std::scoped_lock
(C++17)用于同时管理多个互斥锁,避免死锁。
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
| #include <iostream> #include <mutex> #include <thread>
std::mutex mtx1, mtx2;
void perform_operation_with_1st_mutex() { std::cout << "Thread " << std::this_thread::get_id() << " perform_operation_with_1st_mutex start" << std::endl; std::unique_lock<std::mutex> lock(mtx1); std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Thread " << std::this_thread::get_id() << " perform_operation_with_1st_mutex done" << std::endl; }
void perform_operation_with_2nd_mutex() { std::cout << "Thread " << std::this_thread::get_id() << " perform_operation_with_2nd_mutex start" << std::endl; std::unique_lock<std::mutex> lock(mtx2); std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Thread " << std::this_thread::get_id() << " perform_operation_with_2nd_mutex done" << std::endl; }
void perform_operation_with_2_mutex() { std::cout << "Thread " << std::this_thread::get_id() << " perform_operation_with_2_mutex start" << std::endl; std::scoped_lock lock(mtx1, mtx2); std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Thread " << std::this_thread::get_id() << " perform_operation_with_2_mutex done" << std::endl; }
int main() { std::thread t1(perform_operation_with_2_mutex); std::thread t2(perform_operation_with_1st_mutex); std::thread t3(perform_operation_with_2nd_mutex);
t1.join(); t2.join(); t3.join(); return 0; }
|
特点:
- 可以同时锁定多个互斥量
- 自动避免死锁
- RAII 风格管理
5. 读写锁:shared_mutex
std::shared_mutex
(C++17)支持读写分离的场景,允许多个读操作同时进行。
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
| #include <iostream> #include <mutex> #include <shared_mutex> #include <thread>
std::shared_mutex mtx;
void read_data() { std::shared_lock<std::shared_mutex> lock(mtx); std::cout << "Reading data..." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Thread " << std::this_thread::get_id() << " Reading data done" << std::endl; }
void write_data() { std::unique_lock<std::shared_mutex> lock(mtx); std::cout << "Writing data..." << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); std::cout << "Thread " << std::this_thread::get_id() << " Writing data done" << std::endl; }
int main() { std::thread t1(read_data); std::thread t2(read_data); std::thread t3(write_data);
t1.join(); t2.join(); t3.join();
return 0; }
|
特点:
- 支持共享(读)和独占(写)两种访问模式
- 多个读操作可以并发
- 写操作需要独占访问
6. 尝试锁定:try_lock 和 try_to_lock_t
两种不同的尝试锁定方式:
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 53
| #include <iostream> #include <mutex> #include <thread>
std::mutex mtx;
bool try_lock_mutex() { if (mtx.try_lock()) { std::cout << "Mutex locked using try_lock()" << std::endl; mtx.unlock(); return true; } else { std::cout << "Failed to lock mutex using try_lock()" << std::endl; return false; } }
bool try_lock_with_unique_lock() { std::unique_lock<std::mutex> lock(mtx, std::try_to_lock);
if (lock.owns_lock()) { std::cout << "Mutex locked using unique_lock with try_to_lock" << std::endl; return true; } else { std::cout << "Failed to lock mutex using unique_lock with try_to_lock" << std::endl; return false; } }
int main() { std::cout << "Testing try_lock():" << std::endl; std::thread t1(try_lock_mutex); std::thread t2(try_lock_mutex); t1.join(); t2.join();
std::cout << "\nTesting try_to_lock_t:" << std::endl; std::thread t3(try_lock_with_unique_lock); std::thread t4(try_lock_with_unique_lock); t3.join(); t4.join();
return 0; }
|
特点:
try_lock()
:函数调用方式
try_to_lock_t
:用于 RAII 方式的锁管理
总结
C++ 提供了丰富的锁机制,适应不同的场景需求:
- 简单场景使用
lock_guard
- 需要灵活控制时使用
unique_lock
- 需要超时机制时使用
timed_mutex
- 多锁场景使用
scoped_lock
- 读写分离场景使用
shared_mutex
选择合适的锁机制对于编写高效的多线程程序至关重要。建议优先使用高级的 RAII 风格锁管理器,避免手动管理锁的状态。