1、互斥锁

在编程中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象。

#include <iostream>
#include <boost/thread.hpp>
using namespace std;
int g_num = 0;
boost::mutex mu;  //定义互斥锁对象
int Func(int nCount)
{
    for (int i = 0; i < nCount; i++)
    {
        boost::mutex::scoped_lock lock(mu);  //对共享数据进行操作,需加锁
        g_num++;
        cout << __FUNCTION__ << ": " << g_num << endl;
    }
    return g_num;
}
int _tmain(int argc, _TCHAR* argv[])
{
    boost::thread th1(Func, 100);
    boost::thread th2(Func, 200);
    th1.join();
    th2.join();
    return 0;
}

2、读写锁

boost::shared_mutex rw_mu;   //定义读写锁
int Write(int nCount)
{
    for (int i = 0; i < nCount; i++)
    {
        boost::unique_lock<boost::shared_mutex> lock(rw_mu);   //加唯一锁
        g_num++;
        cout << __FUNCTION__ << ": " << g_num << endl;
    }
    return g_num;
}
void Read(int nCount)
{
    for (int i = 0; i < nCount; i++)
    {
        boost::shared_lock<boost::shared_mutex> lock(rw_mu);  //加共享锁
        cout << __FUNCTION__ << ": " << g_num << endl;
    }
}
int _tmain(int argc, _TCHAR* argv[])
{
    boost::thread th1(Write, 100);
    boost::thread th2(Read, 100);
    boost::thread th3(Read, 100);
    th1.join();
    th2.join();
    th3.join();
    return 0;
}

3、条件量

条件量相对于互斥锁和读写锁来说,并不是那么好理解,简单点说,条件变量就是用于等待某个条件被触发,但为什么要配合锁使用呢,因为我们的等待不能是干等,那样可能会出现死锁。

如线程A负责添加任务到队列,线程B负责处理队列中的任务,队列就是两个线程的共享资源,使用前必须加锁,但如果B线程加锁后,发现队列中没有数据,然后等待,A线程准备添加任务时,发现

锁已经被占用,于是就没法添加任务,就形成了死锁。但如果我等待时,释放锁资源,A线程就能正常添加任务,完成后通知B线程可以处理了,那么整个流程就畅通无阻了,这就是条件量的作用。

#include <queue>
boost::mutex g_ioMutex;    //输出控制锁
template<typename T>
class CMsgQueue
{
public:
    CMsgQueue(size_t n):m_nCapacity(n)
    {
    }
    void Push(const T& val)
    {
        {
            boost::mutex::scoped_lock lock(m_mu);              //加锁
            while(m_val.size() == m_nCapacity)                 //队列已满
            {
                {
                    boost::mutex::scoped_lock lock(g_ioMutex);
                    cout << "队列已满" << endl;
                }
                m_condPush.wait(m_mu);                         //等待,将暂时的解锁
            }
             m_val.push(val);                                   //添加数据到队列
        }
        m_condPop.notify_one();                                 //通知读线程
    }
    void Pop(T& val)
    {
        {
            boost::mutex::scoped_lock lock(m_mu);               //加锁
            while(m_val.size() == 0)                            //队列为空
            {
                {
                    boost::mutex::scoped_lock lock(g_ioMutex);
                    cout << "队列为空" << endl;
                }
                m_condPop.wait(m_mu);                           //等待可读,
            }
            val = m_val.front();                                 //读取数据
            m_val.pop();
        }
        m_condPush.notify_one();                                 //通知写线程
    }
private:
    queue<T> m_val;                            //队列
    int m_nCapacity;                           //队列最大容量
    boost::condition_variable_any m_condPush;  //写入条件量
    boost::condition_variable_any m_condPop;   //读取条件量
    boost::mutex m_mu;                         //互斥锁
};
CMsgQueue<int> g_numQueue(10);
void FuncA(int nCount)
{
    for (int i = 0; i < nCount; i++)
    {
        {
            boost::mutex::scoped_lock lock(g_ioMutex);
            cout << __FUNCTION__ << " Put " << i << endl;
        }
        g_numQueue.Push(i);

    }
}
void FuncB(int nCount)
{
    for (int i = 0; i < nCount; i++)
    {
        int val;
        g_numQueue.Pop(val);
        boost::mutex::scoped_lock lock(g_ioMutex);
        cout << __FUNCTION__ << " Get " << val << endl;
    }
}
int _tmain(int argc, _TCHAR* argv[])
{
    boost::thread th1(FuncA, 50);
    boost::thread th2(FuncB, 20);
    boost::thread th3(FuncB, 30);
    th1.join();
    th2.join();
    th3.join();
    return 0;
}

在多线程程序中,锁的使用需要特别的小心,比如,我们将FuncA稍微改一下:

void FuncA(int nCount)
{
    for (int i = 0; i < nCount; i++)
    {
        boost::mutex::scoped_lock lock(g_ioMutex);
        cout << __FUNCTION__ << " Put " << i << endl;
        g_numQueue.Push(i);
    }
}

如果改成这样,程序将陷入死锁,我们轻轻松松就制造了一个死锁案例。

A线程占用了输入锁,那么B线程的Pop函数将一直在获取输入锁的地方等待,但它已经占用了m_mu锁,A线程也就只能一直在等待m_mu,故形成了死锁。

(十一)boost库之多线程间通信相关推荐

  1. 单线程间通信 多线程间通信

    单线程间通信 首先实现一个EventQueue,该Queue有如下三种状态: ·队列满--最多可容纳多少个Event,好比一个系统最多同时能够受理多少业务一样: ·队列空--当所有的Event都被处理 ...

  2. (十二)boost库之多线程高级特性

    很多时候,线程不仅仅是执行一些耗时操作,可能我们还需要得到线程的返回值,一般的处理方法就是定义一个全局状态变量,不断轮训状态,就如我目前维护的一个项目,全局变量定义了N中状态,看的让人抓狂.该项目的大 ...

  3. MFC VC++多线程间通信

    线程间的通信 1.线程之间的通信简介 一般而言,在一个应用程序中(即进程),一个线程往往不是孤立存在的,常常需要和其它线程通信,以执行特定的任务.如主线程和次线程,次线程与次线程,工作线程和用户界面线 ...

  4. 十一、线程与线程间通信

    目录 线程 一.线程中的基本概念 二.线程的创建和使用 方式一:Thread类 方式二:实现Runnable接口 三.线程状态 常见方法 join方法 sleep方法 Interrupt 方法 yie ...

  5. Linux多线程间通信和多进程间通信的方式

    文章目录 一.进程间的通信方式 1. 进程间通信的概念 1.1. 进程通信的目的: 1.2. Linux 进程间通信(IPC)的发展 2. 进程间通信的7种方式 2.1. 管道/匿名管道(pipe) ...

  6. MFC 多线程间通信

     AfxBeginThead 全局变量 参数传递 消息传递 线程通信 目录(?)[-] 线程间的通信 线程之间的通信简介 全局变量方式 参数传递方式 消息传递方式 线程同步法 线程间的通信 1.线 ...

  7. (十)boost库之多线程

    1.创建线程 使用boost库可以方便的创建一个线程,并提供最多支持9个参数的线程函数,相对于void*来说,方便了很多,创建线程主要提供了一下3种方式: 线程库头文件:#include <bo ...

  8. android 多线程间通信,android实现线程间通信的四种常见方式

    1,通过Handler机制 主线程中定义Handler,子线程发消息,通知Handler完成UI更新,Handler对象必须定义在主线程中,如果是多个类直接互相调用,就不是很方便,需要传递conten ...

  9. 多线程间通信之AutoResetEvent和ManualResetEvent的原理分析

    AutoResetEvent 允许线程通过发信号互相通信. 通常,当线程需要独占访问资源时使用该类. 线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号. 如果 AutoRe ...

最新文章

  1. “斐波那契数列”的两种算法
  2. DL框架:主流深度学习框架(TensorFlow/Pytorch/Caffe/Keras/CNTK/MXNet/Theano/PaddlePaddle)简介、多个方向比较、案例应用之详细攻略
  3. textView不能完全显示时,滚动显示
  4. 苏宁易购上半年营收936.06亿元,零售云加盟店新开1381家
  5. iQOO手机正式发布,全新性能旗舰打造爆燃体验
  6. SQL alter操作
  7. OpenStack温哥华峰会Day2日记:大数据带你看峰会热点
  8. python-opencv-使图片更清晰的几种方法
  9. 物联网应用技术有哪些?
  10. TFT显示屏开发(一):接口定义和型号选择(0.96寸和1.8寸)
  11. 国内外大厂扑向AR-HUD,但抵达“智能汽车终局”仍隔数层纱
  12. 力扣:编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。
  13. 华硕e202s安装linux系统,华硕笔记本E202S原装win10系统可以改win7吗?
  14. Html help安装步骤,Doxgen+Graphiz+htmlhelp配置
  15. 日常英语与计算机专业英语之间的区别,日常英语与计算机专业英语的区别-计算机英语论文-计算机论文(9页)-原创力文档...
  16. HDU1179 Ollivanders
  17. gear s3刷android wear,三星gear s3怎么刷机教程 三星gear s3刷机方法流程
  18. So Cool LINUX 3D桌面
  19. 基于Office Project 2010 管理软件研发项目新体验
  20. GHOST系统备份图解

热门文章

  1. 分区数据导出功能(页面调整)
  2. 集合元素处理(Stream方式)
  3. Java消息队列--ActiveMq 初体验
  4. 数据拆分缺点和解决方案
  5. JAVA程序中 + 号的使用
  6. 浅谈HashMap的实现原理
  7. iOS中AVFoundation的简单使用—音乐的播放
  8. objective c的注释规范
  9. 小功能隐藏着大学问---windows的ACL带来的挑战
  10. 现代网络管理员必备技能