多线程基础
多线程基础[1][2]
线程
std::thread
注意事项
- 线程在
thread
对象初始化后立即执行(等待任何OS调度延迟) - 在
thread
对象销毁前,需要先使用join
或detach
,否则会被调用std::terminate
join
与detach
的区别:join
:调用join
后阻塞当前线程直到被调用join
的线程执行结束detach
:不会等待线程结束,当主线程结束时,其他detach
的线程也会结束
std::this_thread::yield()
可以让出当前处理机
互斥
递归锁 可以在一个线程中多次
lock
,一个线程获取递归锁后其他线程申请此锁时会被阻塞
时间锁 有for
和until
类型 | 说明 |
---|---|
std::mutex | 最基本的 Mutex 类 |
std::recursive_mutex | 递归 Mutex 类 |
std::time_mutex | 定时 Mutex 类 |
std::recursive_timed_mutex | 定时递归 Mutex 类 |
常用操作
lock
:锁定互斥,若互斥不可用则阻塞try_lock
:尝试锁定互斥,若互斥不可用则返回unlock
:解锁互斥
更好的锁定方式 lock_guard
创建 lock_guard 对象时,尝试获取互斥锁的所有权,当控制流离开 lock_guard 对象的作用域时,lock_guard 析构并释放互斥量
int num = 0;
mutex num_mutex;
void safe_increment() {
num_mutex.lock();
++num;
num_mutex.unlock()
}
void safe_increment_with_lock_guard() {
// lock 销毁时自动 unlock
const lock_guard<mutex> lock(num_mutex);
++num;
}
std::lock
和 std::try_lock
可以采用免死锁的方式对两个及以上互斥量上锁,若调用 lock 或 unlock 导致异常,则在重抛前对任何已锁的对象调用 unlock 。
std::scoped_lock
提供此函数的RAII
包装,通常它比裸调用std::lock
更好。