boost库中thread多线程详解2——mutex与lock

1. mutex对象类

mutex类主要有两种:独占式与共享式的互斥量。
▲ 独占式互斥量:
mutex: 独占式的互斥量,是最简单最常用的一种互斥量类型
try_mutex: 它是mutex的同义词,为了与兼容以前的版本而提供
timed_mutex: 它也是独占式的互斥量,但提供超时锁定功能
▲ 递归式互斥量:
recursive_mutex: 递归式互斥量,可以多次锁定,相应地也要多次解锁
recursive_try_mutex: 它是recursive_mutex 的同义词,为了与兼容以前的版本而提供
recursive_timed_mutex: 它也是递归式互斥量,基本功能同recursive_mutex, 但提供超时锁定功能
▲ 共享式互斥量:
shared_mutex: multiple-reader/single-writer 型的共享互斥量(又称读写锁)。
其中mutex有lock和unlock方法,shared_mutex除了提供lock和unlock方法外,还有shared_lock和shared_unlock方法。

2. lock模板类

▲ 独占锁:
boost::unique_lock<T>,其中T可以mutex中的任意一种。
  如果T为mutex,那么boost::unique_lock<boost::mutex>,构造与析构时则分别自动调用lock和unlock方法。
  如果T为shared_mutex,那么boost::unique_lock<boost::shared_mutex>,构造与析构时则分别调用shared_mutex的shared_lock和shared_unlock方法。
注意:scoped_lock也是独占锁,其源代码中定义如下;
  typedef unique_lock<mutex> scoped_lock;
  typedef unique_lock<timed_mutex> scoped_timed_lock;
▲ 共享锁:
boost::shared_lock<T>,其中的T只能是shared_mutex类。
当然还有其他一些锁:lock_guard, upgrade_lock等。

3. 读写锁的实现

[cpp] view plaincopyprint?

 

  1. typedef boost::shared_lock<boost::shared_mutex> readLock;  
  2. typedef boost::unique_lock<boost::shared_mutex> writeLock;  
  3. boost::shared_mutex rwmutex;  
  4.   
  5. void readOnly()  
  6. {  
  7.   readLock rdlock(rwmutex);  
  8.   // do something  
  9. }  
  10.   
  11. void writeOnly()  
  12. {  
  13.   writeLock wtlock(rwmutex);  
  14.   // do something  
  15. }  

对同一个rwmutex,线程可以同时有多个readLock,这些readLock会阻塞任意一个企图获得writeLock的线程,直到所有的readLock对象都析构。如果writeLock首先获得了rwmutex,那么它会阻塞任意一个企图在rwmutex上获得readLock或者writeLock的线程。

4. boost::lock_guard<>和boost::unique_lock<>的区别

[cpp] view plaincopyprint?

 

  1. boost::mutex m;  
  2. void foo( )  
  3. {  
  4.   boost::lock_guard<boost::mutex> lk(m);  
  5.   process(data);  
  6. };  
  7.   
  8. // lock_guard只能像上面这样使用,而unique_lock允许设置超时,推迟锁定lock以及在对象销毁之前unlock。  
  9. {  
  10.   boost::unique_lock<boost::mutex> lk( m );  
  11.   process( data );  
  12.   lk.unlock( );  
  13.   // do other thing  
  14. };  
  15.   
  16. // 设置锁超时  
  17. {  
  18.   boost::unique_lock<boost::timed_mutex> lk(m, std::chrono::milliseconds(3)); // 超时3秒  
  19.   if(lk)  
  20.     process( data );  
  21. };  

 

5. 简单示例

[cpp] view plaincopyprint?

 

    1. namespace  
    2. {  
    3.     boost::mutex mutex;  
    4.     boost::shared_mutex shared_mutex;  
    5.   
    6.     void wait(int seconds)  
    7.     {  
    8.         boost::this_thread::sleep(boost::posix_time::seconds(seconds));  
    9.     }  
    10.   
    11.     void threadfun1()  
    12.     {  
    13.         for (int i = 0; i < 5; ++i)  
    14.         {  
    15.             wait(1);  
    16.             mutex.lock();  
    17.             PRINT_DEBUG(i);  
    18.             mutex.unlock();  
    19.         }  
    20.     }  
    21.   
    22.     void threadfun2()  
    23.     {  
    24.         for (int i = 0; i < 5; ++i)  
    25.         {  
    26.             wait(1);  
    27.             boost::lock_guard<boost::mutex> lock(mutex);  
    28.             PRINT_DEBUG(i);  
    29.         }  
    30.     }  
    31.       
    32.     void threadfun3()  
    33.     {  
    34.         for (int i = 0; i < 5; ++i)  
    35.         {  
    36.             wait(1);  
    37.             // unique_lock<boost::mutex> = scoped_lock  
    38.             boost::unique_lock<boost::mutex> lock(mutex);  
    39.             std::cout << lock.owns_lock() << std::endl;  
    40.             PRINT_DEBUG(i);  
    41.         }  
    42.     }  
    43. }  
    44.   
    45. // 1. mutex例子  
    46. void test_thread_syn1()  
    47. {  
    48.     boost::thread t1(&threadfun1);  
    49.     boost::thread t2(&threadfun1);  
    50.   
    51.     t1.join();  
    52.     t2.join();  
    53. }  
    54.   
    55. //  2. lock_guard例子  
    56. void test_thread_syn2()  
    57. {  
    58.     boost::thread t1(&threadfun2);  
    59.     boost::thread t2(&threadfun2);  
    60.   
    61.     t1.join();  
    62.     t2.join();  
    63. }  
    64.   
    65. // 3. scoped_lock例子  
    66. void test_thread_syn3()  
    67. {  
    68.     boost::thread t1(&threadfun3);  
    69.     boost::thread t2(&threadfun3);  
    70.   
    71.     t1.join();  
    72.     t2.join();  
    73. }  
时间: 2024-11-05 18:31:55

boost库中thread多线程详解2——mutex与lock的相关文章

Java Thread多线程详解及用法解析_java

最全面的java多线程用法解析,如果你对Java的多线程机制并没有深入的研究,那么本文可以帮助你更透彻地理解Java多线程的原理以及使用方法. 1.创建线程 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例.Thread构造函数: public Thread( ); public Thread(Runnab

C++中Boost库裁剪与其应用详解_C 语言

前言 Boost 库涵盖的范围极广,有字符串和文本处理相关子库比如 format 库和 regexp 库,有容器相关子库比如 variant 库(和 Qt 的 QVariant 有得一拼),有迭代器子库比如 tokenizer 库(可以把字符进行 tokenize),还有算法.函数对象和高阶编程相关子库如functional 库.lambda 库和 signal 库,还有泛型编程.模板编程子库如 call traits.mpl,还有并发编程相关的 thread 库,等等等等. Boost 是如此

Linux下多线程中的信号处理详解教程

在linux下,每个进程都有自己的signal mask,这个信号掩码指定哪个信号被阻塞,哪个不会被阻塞,通常用调用sigmask来处理.同时每个进程还有自己的signal action,这个行为集合指定了信号该如何处理,通常调用sigaction来处理. 使用了多线程后,便有些疑问: 信号发生时,哪个线程会收到是不是每个线程都有自己的mask及action每个线程能按自己的方式处理信号么 首先,信号的传递是根据情况而定的: 如果是异常产生的信号(比如程序错误,像SIGPIPE.SIGEGV这些

4.0中的并行计算和多线程详解(二)

相关文章:4.0中的 并行计算和多线程详解(一) 多线程部分 多线程在4.0中被简化了很多,仅仅只需要用到System.Threading.Tasks.::.Task类,下面就来详细介绍下Task类的使用. 一.简单使用 开启一个线程,执行循环方法,返回结果.开始线程为Start(),等待线程结束为Wait(). Code         /// <summary>         /// Task简单使用         /// </summary>         privat

一起谈.NET技术,4.0中的并行计算和多线程详解(二)

相关文章:4.0中的并行计算和多线程详解(一) 多线程部分 多线程在4.0中被简化了很多,仅仅只需要用到System.Threading.Tasks.::.Task类,下面就来详细介绍下Task类的使用. 一.简单使用 开启一个线程,执行循环方法,返回结果.开始线程为Start(),等待线程结束为Wait(). Code         /// <summary>         /// Task简单使用         /// </summary>         private

Linux中线程使用详解

Linux下多线程详解pdf文档下载:点击这里! 线程与进程为什么有了进程的概念后,还要再引入线程呢?使用多线程到底有哪些好处?什么的系统应该选用多线程?我们首先必须回答这些问题. 使用多线程的理由之一是和进程相比,它是一种非常"节俭"的多任务操作方式.我们知道,在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段.堆栈段和数据段,这是一种"昂贵"的多任务工作方式.而运行于一个进程中的多个线程,它们彼此之间使用相同的地址空

Android Handler多线程详解_Android

Android--多线程之Handler 前言 Android的消息传递机制是另外一种形式的"事件处理",这种机制主要是为了解决Android应用中多线程的问题,在Android中不 允许Activity新启动的线程访问该Activity里的UI组件,这样会导致新启动的线程无法改变UI组件的属性值.但实际开发中,很多地方需要在 工作线程中改变UI组件的属性值,比如下载网络图片.动画等等.本篇博客主要介绍Handler是如何发送与处理线程上传递来的消息,并讲解 Message的几种传递数

Android 多线程处理之多线程详解_Android

handler.post(r)其实这样并不会新起线程,只是执行的runnable里的run()方法,却没有执行start()方法,所以runnable走的还是UI线程. 1.如果像这样,是可以操作ui,但是run还是走在主线程,见打印出来的Log线程名字是main,说明是主线程. 这就是为什么可以直接在run方法里操作ui,因为它本质还是ui线程 handler.post(new Runnable(){ public void run(){ Log.e("当前线程:",Thread.c

java 线程创建多线程详解_java

Java 线程类也是一个 object 类,它的实例都继承自 java.lang.Thread 或其子类. 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法: Tread thread = new Thread(); thread.start(); 在上面的例子中,我们并没有为线程编写运行代码,因此调用该方法后线程就终止了. 编写线程运行时执行的代码有两种方式:一种是创建 Thread 子类的一个实例并重写 run 方法,第二种是创建类的时候实现 Run