转自:http://www.cnblogs.com/haippy/p/3237213.html

上一篇《C++11 并发指南二(std::thread 详解)》中主要讲到了 std::thread 的一些用法,并给出了两个小例子,本文将介绍 std::mutex 的用法。

Mutex 又称互斥量,C++ 11中与 Mutex 相关的类(包括锁类型)和函数都声明在 <mutex> 头文件中,所以如果你需要使用 std::mutex,就必须包含 <mutex> 头文件。

<mutex> 头文件介绍

Mutex 系列类(四种)

  • std::mutex,最基本的 Mutex 类。
  • std::recursive_mutex,递归 Mutex 类。
  • std::time_mutex,定时 Mutex 类。
  • std::recursive_timed_mutex,定时递归 Mutex 类。

Lock 类(两种)

  • std::lock_guard,与 Mutex RAII 相关,方便线程对互斥量上锁。
  • std::unique_lock,与 Mutex RAII 相关,方便线程对互斥量上锁,但提供了更好的上锁和解锁控制。

其他类型

  • std::once_flag
  • std::adopt_lock_t
  • std::defer_lock_t
  • std::try_to_lock_t

函数

  • std::try_lock,尝试同时对多个互斥量上锁。
  • std::lock,可以同时对多个互斥量上锁。
  • std::call_once,如果多个线程需要同时调用某个函数,call_once 可以保证多个线程对该函数只调用一次。

std::mutex 介绍

下面以 std::mutex 为例介绍 C++11 中的互斥量用法。

std::mutex 是C++11 中最基本的互斥量,std::mutex 对象提供了独占所有权的特性——即不支持递归地对 std::mutex 对象上锁,而 std::recursive_lock 则可以递归地对互斥量对象上锁。

std::mutex 的成员函数

  • 构造函数,std::mutex不允许拷贝构造,也不允许 move 拷贝,最初产生的 mutex 对象是处于 unlocked 状态的。
  • lock(),调用线程将锁住该互斥量。线程调用该函数会发生下面 3 种情况:(1). 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁。(2). 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
  • unlock(), 解锁,释放对互斥量的所有权。
  • try_lock(),尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞。线程调用该函数也会出现下面 3 种情况,(1). 如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量。(2). 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉。(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。

下面给出一个与 std::mutex 的小例子(参考

 #include <iostream>       // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex volatile int counter(); // non-atomic counter
std::mutex mtx; // locks access to counter void attempt_10k_increases() {
for (int i=; i<; ++i) {
if (mtx.try_lock()) { // only increase if currently not locked:
++counter;
mtx.unlock();
}
}
} int main (int argc, const char* argv[]) {
std::thread threads[];
for (int i=; i<; ++i)
threads[i] = std::thread(attempt_10k_increases); for (auto& th : threads) th.join();
std::cout << counter << " successful increases of the counter.\n"; return ;
}

std::recursive_mutex 介绍

std::recursive_mutex 与 std::mutex 一样,也是一种可以被上锁的对象,但是和 std::mutex 不同的是,std::recursive_mutex 允许同一个线程对互斥量多次上锁(即递归上锁),来获得对互斥量对象的多层所有权,std::recursive_mutex 释放互斥量时需要调用与该锁层次深度相同次数的 unlock(),可理解为 lock() 次数和 unlock() 次数相同,除此之外,std::recursive_mutex 的特性和 std::mutex 大致相同。

std::time_mutex 介绍

std::time_mutex 比 std::mutex 多了两个成员函数,try_lock_for(),try_lock_until()。

try_lock_for 函数接受一个时间范围,表示在这一段时间范围之内线程如果没有获得锁则被阻塞住(与 std::mutex 的 try_lock() 不同,try_lock 如果被调用时没有获得锁则直接返回 false),如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁,如果超时(即在指定时间内还是没有获得锁),则返回 false。

try_lock_until 函数则接受一个时间点作为参数,在指定时间点未到来之前线程如果没有获得锁则被阻塞住,如果在此期间其他线程释放了锁,则该线程可以获得对互斥量的锁,如果超时(即在指定时间内还是没有获得锁),则返回 false。

下面的小例子说明了 std::time_mutex 的用法(参考)。

 #include <iostream>       // std::cout
#include <chrono> // std::chrono::milliseconds
#include <thread> // std::thread
#include <mutex> // std::timed_mutex std::timed_mutex mtx; void fireworks() {
// waiting to get a lock: each thread prints "-" every 200ms:
while (!mtx.try_lock_for(std::chrono::milliseconds())) {
std::cout << "-";
}
// got a lock! - wait for 1s, then this thread prints "*"
std::this_thread::sleep_for(std::chrono::milliseconds());
std::cout << "*\n";
mtx.unlock();
} int main ()
{
std::thread threads[];
// spawn 10 threads:
for (int i=; i<; ++i)
threads[i] = std::thread(fireworks); for (auto& th : threads) th.join(); return ;
}

std::recursive_timed_mutex 介绍

和 std:recursive_mutex 与 std::mutex 的关系一样,std::recursive_timed_mutex 的特性也可以从 std::timed_mutex 推导出来,感兴趣的同鞋可以自行查阅。 ;-)

std::lock_guard 介绍

与 Mutex RAII 相关,方便线程对互斥量上锁。例子(参考):

 #include <iostream>       // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::lock_guard
#include <stdexcept> // std::logic_error std::mutex mtx; void print_even (int x) {
if (x%==) std::cout << x << " is even\n";
else throw (std::logic_error("not even"));
} void print_thread_id (int id) {
try {
// using a local lock_guard to lock mtx guarantees unlocking on destruction / exception:
std::lock_guard<std::mutex> lck (mtx);
print_even(id);
}
catch (std::logic_error&) {
std::cout << "[exception caught]\n";
}
} int main ()
{
std::thread threads[];
// spawn 10 threads:
for (int i=; i<; ++i)
threads[i] = std::thread(print_thread_id,i+); for (auto& th : threads) th.join(); return ;
}

std::unique_lock 介绍

与 Mutex RAII 相关,方便线程对互斥量上锁,但提供了更好的上锁和解锁控制。例子(参考):

相当于autolock,在析构时调用unlock

 #include <iostream>       // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock std::mutex mtx; // mutex for critical section void print_block (int n, char c) {
// critical section (exclusive access to std::cout signaled by lifetime of lck):
std::unique_lock<std::mutex> lck (mtx);
for (int i=; i<n; ++i) {
std::cout << c;
}
std::cout << '\n';
} int main ()
{
std::thread th1 (print_block,,'*');
std::thread th2 (print_block,,'$'); th1.join();
th2.join(); return ;
}

C++11 并发指南三(std::mutex 详解)(转)的更多相关文章

  1. 【C/C++开发】C++11 并发指南三(std::mutex 详解)

    本系列文章主要介绍 C++11 并发编程,计划分为 9 章介绍 C++11 的并发和多线程编程,分别如下: C++11 并发指南一(C++11 多线程初探)(本章计划 1-2 篇,已完成 1 篇) C ...

  2. C++11 并发指南三(std::mutex 详解)

    上一篇<C++11 并发指南二(std::thread 详解)>中主要讲到了 std::thread 的一些用法,并给出了两个小例子,本文将介绍 std::mutex 的用法. Mutex ...

  3. C++11 并发指南五(std::condition_variable 详解)

    前面三讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三(std::mutex 详解)>分别介绍了 std::thread,std::mut ...

  4. C++11 并发指南五(std::condition_variable 详解)(转)

    前面三讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三(std::mutex 详解)>分别介绍了 std::thread,std::mut ...

  5. 【转】C++11 并发指南五(std::condition_variable 详解)

    http://www.cnblogs.com/haippy/p/3252041.html 前面三讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三 ...

  6. C++11 并发指南二(std::thread 详解)

    上一篇博客<C++11 并发指南一(C++11 多线程初探)>中只是提到了 std::thread 的基本用法,并给出了一个最简单的例子,本文将稍微详细地介绍 std::thread 的用 ...

  7. C++11 并发指南二(std::thread 详解)(转)

    上一篇博客<C++11 并发指南一(C++11 多线程初探)>中只是提到了 std::thread 的基本用法,并给出了一个最简单的例子,本文将稍微详细地介绍 std::thread 的用 ...

  8. 【C/C++开发】C++11 并发指南二(std::thread 详解)

    上一篇博客<C++11 并发指南一(C++11 多线程初探)>中只是提到了 std::thread 的基本用法,并给出了一个最简单的例子,本文将稍微详细地介绍 std::thread 的用 ...

  9. C++11 并发指南六(atomic 类型详解三 std::atomic (续))

    C++11 并发指南六( <atomic> 类型详解二 std::atomic ) 介绍了基本的原子类型 std::atomic 的用法,本节我会给大家介绍C++11 标准库中的 std: ...

随机推荐

  1. Linux进程间通信(IPC)

    linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的.而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...

  2. SVM用于线性回归

    SVM用于线性回归 方法分析 在样本数据集()中,不是简单的离散值,而是连续值.如在线性回归中,预测房价.与线性回归类型,目标函数是正则平方误差函数: 在SVM回归算法中,目的是训练出超平面,采用作为 ...

  3. Spring事务管理接口PlatformTransactionManager的实现类DataSourceTransactionManager

    package org.springframework.jdbc.datasource; import java.sql.Connection; import java.sql.SQLExceptio ...

  4. ASP.NET配置设置-关于web.config各节点的讲解

    在msdn中搜索:“ASP.NET配置设置”,可以查看各个节点的配置. httpRuntime 元素:配置 ASP.NET HTTP 运行时设置,以确定如何处理对 ASP.NET 应用程序的请求.

  5. 关于 __int128

    __int128 是 GCC 提供的扩展(extension),可以当作 128 位整数使用. 关于 __int128 和 __int128_t Normally, _t suffix means a ...

  6. 刷题总结——天使玩偶(bzoj2716)

    题目: Description Input Output HINT 题解: 学了cdq后近期最后一道题···然而tm还是搞了1个半小时才tm搞出来······ 先说思路:对于绝对值,我们采取类似于旋转 ...

  7. 学习的一些mybatis

    MyBatis入门基础(一) 阅读目录 一:对原生态JDBC问题的总结 二:MyBatis框架 三:mybatis入门程序 四:mybatis和Hibernate的本质区别与应用场景 五:小结 回到顶 ...

  8. Linux 系统自动备份数据库及定时任务的设置

    首先想到数据库的自动备份,由于涉及业务原因需要在每天固定的时间去调用方法执行备份.如果不考虑业务要求,只考虑实现的话可以通过Linux系统提供的定时任务去完成备份操作. 本文讲的就是利用Linux系统 ...

  9. ajax cache enable and ajax concurrency!

    Today, forget to close ajax cache which leads to duplicate result from cache as to Jquery, this way, ...

  10. 【MFC】 点击不同的按钮后在界面同一位置显示不同的对话框内容(转)

    原文转自 http://bbs.csdn.net/topics/391039432 如图类似Tab控件的功能    但Tab控件按钮是固定的上下左右  不方便     所以想自己重新做个这种   我M ...