多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# 互斥 互斥是多线程系统中用于控制访问的一个原对象(primitive object)。下面的例子给出了它最基本的用法: ``` std::mutex m; int sh; //共享数据 // … m.lock(); // 对共享数据进行操作: sh += 1; m.unlock(); ``` 在任何时刻,最多只能有一个线程执行到lock()和unlock()之间的区域(通常称为临界区)。当第一个线程正在临界区执行时,后续执行到m.lock()的线程将会被阻塞直到第一个进程执行到m.unlock()。这个过程比较简单,但是如何正确使用互斥并不简单。错误地使用互斥将会导致一系列严重后果。大家可以设想以下情形所导致的后果:一个线程只进行了lock()而没有执行相应unlock(); 一个线程对同一个mutex对象执行了两次lock()操作;一个线程在等待unlock()操作时被阻塞了很久;一个线程需要对两个mutex对象执行lock()操作后才能执行后续任务。可以在很多书(译者注:通常操作系统相关书籍中会讲到)中找到这些问题的答案。在这里(包括Locks section一节)所给出的都是一些入门级别的。 除了lock(),mutex还提供了try_lock()操作。线程可以借助该操作来尝试进入临界区,这样一来该线程不会在失败的情况下被阻塞。下面例子给出了try_lock()的用法: ``` std::mutex m; int sh; //共享数据 // … if (m.try_lock()) { //操作共享数据 sh += 1; m.unlock(); } else { //可能在试图进入临界区失败后执行其它代码 } ``` recursive_mutex是一种能够被同一线程连续锁定多次的mutex。下面是recursive_mutex的一个实例: ``` std::recursive_mutex m; int sh; //共享数据 //.. void f(int i) { //… m.lock(); //对共享数据进行操作 sh += 1; if (–i>0) f(i); //注意:这里对f(i)进行了递归调用, //将导致在m.unlock()之前多次执行m.lock() m.unlock(); //… } ``` 对于这点,我曾经夸耀过并且用f()调用它自身。一般地,代码会更加微妙。这是因为代码中经常会有间接递归调用。比如f()调用g(),而g()又调用了h(),最后h()又调用了f(),这样就形成了一个间接递归。 如果我想在未来的10秒内进入到一个mutex所划定的临界区,该如果实现? timed_mutex类可以解决这个问题。事实上,关于它的使用可以被看做是关联了时间限制的try_lock()的一个特例。 ``` std::timed_mutex m; int sh; //共享数据 //… if ( m.try_lock_for(std::chrono::seconds(10))) { //对共享数据进行操作 sh += 1; m.unlock(); } else { //进入临界区失败,在此执行其它代码 } ``` try_lock_for()的参数是一个用相对时间表示的duration。如果你不想这么做而是想等到一个固定的时间点:一个time_point,你可以使用try_lock_until(): ``` std::timed_mutex m; int sh; //共享数据 // … if ( m.try_lock_until(midnight)) { //对共享数据进行操作 sh += 1; m.unlock(); } else { //进入临界区失败,在此执行其它代码 } ``` 这里使用midnight是一个冷笑话:对于mutex级别的操作,相应的时间是毫秒级别的而不是小时。 当然地,C++0x中也有recursive_timed_mutex。 mutex可以被看做是一个资源(因为它经常被用来代表一种真实的资源),并且当它对至少两个线程可见时它才是有用的。必然地,mutex不能被复制或者移动(正如你不能复制一个硬件的输入寄存器)。 令人惊讶地,实际中经常很难做到lock()s与unlock()s的匹配。设想一下那些复杂的控制结构,错误以及异常,要做到匹配的确比较困难。如果你可以选择使用locks去管理你的互斥,这将为你和你的用户节省大量的时间,再也不用熬夜通宵彻夜无眠了。(that will save you and your users a lot of sleep??)。 同时可参考: * Standard: 30.4 Mutual exclusion [thread.mutex] * H. Hinnant, L. Crowl, B. Dawes, A. Williams, J. Garland, et al.: [Multi-threading Library for Standard C++ (Revision 1)](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2320.html) * ??? (翻译:Yibo Zhu)