和智能指针一样,thread库也已经被加入到标准了,为了照顾某些不是最新版本的C++编译器,这里还是以boost中的thread为例,其和标准thread几乎一样。
1. build使用boost::thread的代码时,要链接libboost_thread.so和libboost_systrem.so,注意确认库文件名,有时是libboost_thread-mt.so和libboost_systrem-mt.so
2. thread对象是不可拷贝的。如果需要将其放入容器中,一般采用两种方法:(1)使用move语义;(2)初始化一个指向它的智能指针,容器中保存智能指针
3. 线程睡眠
boost::this_thread::sleep(boost::posix_time::seconds(2)); // 本线程睡眠2秒钟4. 使用boost::mutex的lock和unlock方法时,要加上try-catch,确保顺利unlock
// 由于临界区可能抛出异常,为了保证unlock被调用,要加上try-catch
boost::mutex mu;
try {
mu.lock();
std::cout << "critical section" << std::endl; // 临界区
mu.unlock();
} catch(...) {
mu.unlock();
}
5. 优先使用scoped_lock,让加锁和解锁自动化
// 使用大括号,构造出一个作用域,将需要锁保护的操作放入其中,使用自动锁保护
{
boost::mutex mu;
// 构造自动锁对象,在构造函数中完成加锁操作
// 当退出作用域后,自动锁的析构函数被调用,在析构函数中完成解锁操作
boost::mutex::scoped_lock lock(mu);
std::cout << "critical section" << std::endl; // 临界区
}
6. 创建线程
void print_func(int x, const std::string& s) {
std::cout << x << std::endl;
std::cout << s << std::endl;
}
int x = 8;
std::string s("Hello, world")
boost::thread print_thread(print_func, x, s);
7. 线程等待
print_thread.join(); // 等待线程print_thread执行完毕才返回
print_thread.timed_join(boost::posix_time::secodes(10)); // 最多等待线程print_thread执行10秒,可以提前返回
8. 中断线程
print_thread.interrupt();9. 设置中断点
boost::this_thread::interruption_point();10. 启用/禁用中断
boost::this_thread::interruption_enabled(); // 检测当前线程是否允许被中断
boost::this_thread::disable_interruption类,其对象具有RAII性质,构造时禁用中断,析构时自动恢复
boost::this_thread::restore_interruption类,构造时启用中断,析构时禁用中断
{
boost::this_thread::disable_interruption di; // 禁用中断
// do sth
boost::this_thread::interruption_point(); // 中断被禁用,中断点无效
boost::this_thread::restore_interruption ri(di); // 启用中断
// do sth
boost::this_thread::interruption_point(); // 中断点有效,线程被中断
// do sth, but we never get here
}
11. 条件变量优先使用condition_variable_any,它能够适应更广泛的互斥量类型。boost库有个typedef,typedef boost::condition_variable_any boost::condition,所以可以直接使用boost::condition
12. 条件变量使用示例:
// 生产者线程和消费者线程均可访问到的全局变量(相对于它们而言)
boost::mutex mu;
boost::condition_variable_any condi; // 等价于boost::condition condi;
std::queue<std::string> q;
// 消费者线程,q为队列
{
boost::mutex::scoped_lock lock(mu);
while (q.empty()) {
condi.wait(mu);
}
std::string s = q.front();
std::cout << s << std::endl;
}
// 生产者线程
{
boost::mutex::scoped_lock lock(mu);
std::string s("abc");
q.push(s);
condi.notify_one();
}
13. 读写锁shared_mutex
boost::shared_mutex sm; // 读锁定
{
boost::shared_lock<boost::shared_mutex> sl(sm);
// do sth
}
// 写锁定
{
boost::unique_lock<boost::shared_mutex> ul(sm);
// do sth
}
14. 仅初始化一次
static int g_count;
void init_func() {
std::cout << "This init_func function should be called only once" << std::endl;
g_count = 8;
}
void init_func() {
std::cout << "This init_func function should be called only once" << std::endl;
g_count = 8;
}
boost::once_flag of = BOOST_ONCE_INIT;
void call_func() {
call_once(of, init_func);
}
int main() {
boost::thread t1(call_func);
boost::thread t2(call_func);
boost::thread t3(call_func);
t1.join();
t2.join();
t3.join();
return 0;
}
15. cout等流对象在多线程环境下要加锁,它们不是线程安全的