1、互斥锁(互斥量)

mutex是独占式的互斥锁。timed_mutex增加了超时功能。

成员函数:lock()用于锁定,try_lock()为非阻塞版本的锁定,unlock()用于解锁。timed_lock()只属于timed_mutex,它可以等待一定的时间,等待的时间可以是一个时间段,也可以是指定的时间。

使用方法:使用mutex必须配合try-catch块以保证解锁互斥量,eg:

#include "boost\thread.hpp"int main()
{boost::mutex mu;try{mu.lock();cout << "Need to be protected" << endl; //io流是个共享资源,多线程内使用的话需要同步
        mu.unlock();}catch (...){mu.unlock();}return 0;
}

View Code

mutex还提供了一系列的RAII型的互斥锁,用于取消麻烦的try-catch块,它会在构造的时候锁定互斥量,析构时自动解锁,eg:

#include "boost\thread.hpp"int main()
{boost::mutex mu;boost::mutex::scoped_lock lock(mu);cout << "Need to be protected" << endl; //io流是个共享资源,多线程内使用的话需要同步return 0;
}

View Code

使用实例:以下定义了一个支持原子前++的计数器atom_increase:

#include "boost\thread.hpp"template<typename T>
class atom_increase
{
public:atom_increase(T x = 0): n(x){} //转换构造函数,实现T类型到atom_increase类型的隐式转换
T operator++() //重载前++运算符
    {boost::mutex::scoped_lock lock(mu);return ++n;}operator T() { return n; } //类型转换函数,实现atom_increase类型到T类型的隐式转换private:T n;boost::mutex mu;
};int main()
{    atom_increase<int> n = 0; //隐式转换:int -> atom_increase++n; //原子前++int i = 5 + n; //隐式转换:atom_increase ->intreturn 0;
}

View Code

2、递归锁

recursive_mutex是递归锁,可以多次锁定,相应的也要多次解锁。recursive_timed_mutex增加了超时功能。递归锁的使用接口跟互斥锁基本相同。

3、读写锁

shared_mutex是读写锁,提供了multiple-reader / single-writer功能。读取锁定时我们使用shared_lock<shared_mutex>对象,写入锁定时我们使用unique_lock<shared_mutex>对象:

    boost::shared_mutex rw_mu;//read thread
    {boost::shared_lock<boost::shared_mutex> sl(rw_mu); //读锁定//......
    }//write thread
    {boost::unique_lock<boost::shared_mutex> ul(rw_mu); //写锁定//......}

View Code

4、条件变量

condition_variable_any是条件变量,它用来在一个线程中等待某个事件的发生(满足某个条件),另一个线程会使条件成立。条件变量需要与一个互斥量配合使用。condition_variable_any::wait()用来等待条件满足,wait_for()用来等待条件满足直到超时,wait_until()用来等待条件满足直到指定的时间, condition_variable_any::notify_one() / notify_all()用来在条件满足的时候通知条件变量。

boost中的条件变量的使用方法与posix或windows下条件变量使用方法基本一致:

#include "boost\thread.hpp"boost::condition_variable_any g_cd;
boost::mutex g_mu;
bool g_bConditionFlag = false;void Thread1Proc()
{boost::mutex::scoped_lock lock(g_mu);while (!g_bConditionFlag){boost::this_thread::sleep(boost::posix_time::seconds(1));g_cd.wait(g_mu);}printf("thread1 exit\n");
}int main()
{boost::thread t(Thread1Proc);t.detach();boost::this_thread::sleep(boost::posix_time::milliseconds(100));g_mu.lock();g_bConditionFlag = true;g_cd.notify_one();g_mu.unlock();printf("here\n");getchar();return 0;
}

View Code

 5、barrier

barrier称为护栏,它可以用来设置线程执行到barrier时必须等待,直到所有线程都达到这个点时才继续执行。

 6、C++11中的线程操作

c++11也提供了创建线程和线程同步的方法,c++11里的mutex,与boost里的mutex用法类似:

#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <mutex>          // std::mutex, std::lock

std::mutex foo, bar;void task_a()
{// foo.lock(); // bar.lock();std::lock(foo, bar);std::cout << "task a\n";foo.unlock();bar.unlock();
}void task_b()
{// bar.lock(); // foo.lock();std::lock(bar, foo);std::cout << "task b\n";bar.unlock();foo.unlock();
}int main()
{std::thread th1(task_a);std::thread th2(task_b);// th1.detach();// th2.detach();
    th1.join();th2.join();return 0;
}

View Code

创建线程的时候需要注意三点:

①、如果使用函数对象作为thread的参数的话,直接传入临时对象会出错,可以定义一个对象传入或者使用lambda表达式:

class CTask
{
public:void operator()(){int a = 0;}
};//std::thread th1(CTask()); //直接传入临时对象会出错
CTask task;
std::thread th1(task);
th1.join();

View Code

②、传递给线程函数的参数是先保存在于一个中转站中,当函数执行的时候再传给函数的形参,而这个时候传递的参数指向的值很有可能已经失效,所以,对于线程函数传递的参数应该与形参类型相同,而不是再进行转换。

③、如果线程函数的参数是引用的话传入时还需要结合ref来使用。

    void task(int& a, string str){}int iNum = 0;char* pStr = new char[100];strcpy(pStr, "test");//std::thread th(task, 5, std::ref(iNum), pStr); //不应该直接传入pStrstd::thread th(task, std::ref(iNum), string(pStr)); //应该传入对应类型delete[] pStr;th.join();

View Code

c++中的lock_guard、unique_lock也是RAII型的互斥锁,类似boost的scoped_lock,使用示例:

    std::lock_guard<std::mutex> _lock(m_mutex);g_num++;

unique_lock在lock_guard的基础上增加了加锁和解锁的接口方法,对比下面的fun1和fun2,二者效果相同,通过代码可以看出二者区别:

std::mutex g_mu;void fun1()
{{std::lock_guard<std::mutex> guard(g_mu);//do something 1
    }//do something 2
    {std::lock_guard<std::mutex> guard(g_mu);// do something 3
    }
}void fun2()
{std::unique_lock<std::mutex> guard(g_mu);//do something 1
    guard.unlock();//do something 2
guard.lock();// do something 3
}

View Code

unique_lock可以配合条件变量来使用,而lock_guard不能,因为lock_guard没有加锁和解锁的接口方法。另外,unique_lock和lock_guard都不能复制,unique_lock可以移动,lock_guard不能移动。c++11中的条件变量condition_variable与boost的使用类似,其接口方法有wait()、notify_one()等。

转载于:https://www.cnblogs.com/milanleon/p/7591530.html

boost--线程同步相关推荐

  1. 9 C++ Boost 多线程,线程同步

    线程的创建 boost_thread,boost_system 多线程的创建 线程的参数传递 线程的创建方式 线程的join 加入join,回收线程线程中断 线程中断2, 线程组 boost 线程的死 ...

  2. muduo学习笔记 - 第2章 线程同步精要

    第2章 线程同步精要 2.1 互斥器 (mutex) 互斥器保护了临界区,任何时刻最多只能有一个线程在mutex划出的临界区内活动 推荐使用原则: 用RAII手法封装mutex的创建.销毁.加锁.解锁 ...

  3. boost线程(二)

    1 创建线程 就像std::fstream类就代表一个文件一样,boost::thread类就代表一个可执行的线程.缺省构造函数创建一个代表当前执行线程的实例.一个重载的构造函数以一个不需任何参数的函 ...

  4. BOOST 线程完全攻略 - 基础篇 .

    C++多线程开发是一个复杂的事情,mfc下提供了CWinThread类,和AfxBeginThread等等函数,但是在使用中会遇到很多麻烦事情,例如线程之间参数传递的问题,我们一般都是把参数new一个 ...

  5. 线程同步-信号量-strand的用法总结

    这里展示不用boost::asio::strand而是利用常规线程同步的手段来完成线程的同步. #include <iostream> #include <boost/asio.hp ...

  6. Python 多线程总结(2)— 线程锁、线程池、线程数量、互斥锁、死锁、线程同步

    主要介绍使用 threading 模块创建线程的 3 种方式,分别为: 创建 Thread 实例函数 创建 Thread 实例可调用的类对象 使用 Thread 派生子类的方式 多线程是提高效率的一种 ...

  7. 改善C#程序的建议6:在线程同步中使用信号量

    所谓线程同步,就是多个线程之间在某个对象上执行等待(也可理解为锁定该对象),直到该对象被解除锁定.C#中对象的类型分为引用类型和值类型.CLR在这两种类型上的等待是不一样的.我们可以简单的理解为在CL ...

  8. C#线程同步的几种方法

    在网上也看过一些关于线程同步的文章,其实线程同步有好几种方法,下面我就简单的做一下归纳. 一.volatile关键字 volatile是最简单的一种同步方法,当然简单是要付出代价的.它只能在变量一级做 ...

  9. MFC 多线程及线程同步

    一.MFC对多线程编程的支持 MFC中有两类线程,分别称之为工作者线程和用户界面线程.二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环. 工作者线程没有消息机制,通常 ...

  10. java同步与死锁_Java多线程 - 线程同步与死锁

    一.线程同步 1)模拟多个用户同时从银行账户里面取钱 ● Account 类:银行账户类,里面有一些账户的基本信息,以及操作账户信息的方法 //模拟银行账户 classAccount {private ...

最新文章

  1. java 客户端发起http请求2
  2. C# WinForm中 让控件全屏显示的实现代码
  3. 双通道和单通道区别_实测内存通道的区别:单通道比双通道内存更有优势?
  4. Shell编程:简洁的 Bash Programming 技巧续篇
  5. Pytorch---训练与测试时爆显存(out of memory)的一个解决方案(torch.cuda.empty_cache())
  6. 软件测试总结(十一)
  7. php 查看常量值,[thinkphp]查看thinkphp系统定义的常量值
  8. PL/SQL批处理语句(BULK COLLECT子句和FORALL语句)
  9. ArcBlock 将作证支持美国华盛顿州区块链立法 | ABT 活动
  10. chromecast 协议_因此,您刚刚获得了Chromecast。 怎么办?
  11. linux 网站访问日志,网站访问日志的管理--analog使用
  12. Android获取手机设备识别码(IMEI)和手机号码
  13. 【学习笔记】《卓有成效的管理者》 第四章 如何发挥人的长处
  14. python 静态网站生成_最全的静态网站生成器(开源项目)
  15. 2020年阴历三月初一 投资理财~有些大v要警惕
  16. 潜规则------中国历史中的真实游戏 吴思
  17. 构建ubuntu下的JXTA-C开发环境
  18. HDU 4526.威威猫系列故事——拼车记
  19. Java encodeURI
  20. 微信小程序数据填充新闻详情页面

热门文章

  1. kubesphere devops介绍、访问账密及nfs数据备份同步
  2. spring cloud组件服务架构
  3. python3遍历技巧
  4. 在soa工程中使用dubbo的步骤
  5. Apache Shiro 框架简介和下载导入
  6. php定时发送生日模块消息_Swoft 2.0.5 更新,新增高效秒级定时任务、异常管理组件...
  7. 一些Python情结
  8. c++读二进制文件结束的时候总会异常_python专题文件操作
  9. 鼠标右键转圈圈_鼠标右键文件夹出现转圈圈假死机情况
  10. IDE / Qt / 浅谈 qmake 之 pro、pri、prf、prl文件