这篇文章主要介绍“C++11中线程、锁和条件变量的介绍”,在日常操作中,相信很多人在C++11中线程、锁和条件变量的介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++11中线程、锁和条件变量的介绍”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
std::thread类代表了一个可执行的线程,它来自头文件<thread>。与其它创建线程的API(比如 Windows API中的CreateThread)不同的是, 它可以使用普通函数、lambda函数以及仿函数(实现了operator()函数的类)。另外,它还允许向线程函数传递任意数量的参数。
#include <thread> void func() { // do some work } int main() { std::thread t(func); t.join(); return 0; }在上面的例子中,t是一个线程对象,函数func()运行于该线程之中。调用join函数后,该调用线程(本例中指的就是主线程)就会在join进来进行执行的线程t结束执行之前,一直处于阻塞状态。如果该线程函数执行结束后返回了一个值,该值也将被忽略。不过,该函数可以接受任意数量的参数。
void func(int i, double d, const std::string& s) { std::cout << i << ", " << d << ", " << s << std::endl; } int main() { std::thread t(func, 1, 12.50, "sample"); t.join(); return 0; }尽管我们可以向线程函数传递任意数量的参数,但是,所有的参数都是按值传递的。如果需要将参数按引用进行传递,那么就一定要象下例所示一样,把该参数封装到 std::ref或者std::cref之中。
void func(int& a) { a++; } int main() { int a = 42; std::thread t(func, std::ref(a)); t.join(); std::cout << a << std::endl; return 0; }上面程序打印结果为43,但要不是将a封装到std::ref之中的话,输出的将是42。
除join方法之外,这个线程类还提供了另外几个方法:
swap: 将两个线程对象的底层句柄进行交换
detatch: 允许执行该方法的线程独立于本线程对象的执行而继续执行。脱离后的线程就再也不能执行join了(你不能等待到它执行结束了)
<span style="font-family:'Courier New', Arial;font-size:9pt;line-height:1.5;">int</span><span style="font-family:'Courier New', Arial;font-size:9pt;line-height:1.5;"> main()</span> { std::thread t(funct); t.detach(); return 0; }有一点非常重要,值得注意:线程函数中要是抛出了异常的话,使用通常的try-catch方式是捕获不到该异常的。换句话说,下面这种做法行不通:
try { std::thread t1(func); std::thread t2(func); t1.join(); t2.join(); } catch(const std::exception& ex) { std::cout << ex.what() << std::endl; }要在线程间传递异常,你可以先在线程函数中捕获它们,然后再将它们保存到一个合适的地方,随后再让另外一个线程从这个地方取得这些异常。
std::vector<std::exception_ptr> g_exceptions; void throw_function() { throw std::exception("something wrong happened"); } void func() { try { throw_function(); } catch(...) { std::lock_guard<std::mutex> lock(g_mutex); g_exceptions.push_back(std::current_exception()); } } int main() { g_exceptions.clear(); std::thread t(func); t.join(); for(auto& e : g_exceptions) { try { if(e != nullptr) { std::rethrow_exception(e); } } catch(const std::exception& e) { std::cout << e.what() << std::endl; } } return 0; }要获得更多关于捕获并传递异常的知识,你可以阅读在主线程中处理工作线程抛出的C++异常以及怎样才能在线程间传递异常?。
在深入讨论之前还有一点值得注意,头文件<thread>里还在命名空间std::this_thread中提供了一些辅助函数:
get_id: 返回胆怯线程的id
yield: 让调度器先运行其它的线程,这在忙于等待状态时很有用
sleep_for: 将当前线程置于阻塞状态,时间不少于参数所指定的时间段
sleep_util: 在指定的时刻来临前,一直将当前的线程置于阻塞状态
锁
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。