原子操作,基本都包含我们三个方面所关心的语义:
– 操作本身是不可分割的(Atomicity),
– 一个线程对某个数据的操作何时对另外一个线程可见(Visibility),
– 执行的顺序是否可以被重排(Ordering)。
#include <boost/atomic.hpp>
#include <vector>
#include <iostream>
using namespace std;
using namespace boost;
int main()
{
atomic<int> a(10);
assert(a == 10);
atomic<long> b; //未初始化危险!!
cout << b << endl;
//最重要的2成员函数store() load();以原子的方式存取atomic内部值;
atomic<bool> c(false);
assert(!c.load()); //取值
c.store(1); //存值
assert(c.load());
//exchange() 原子地交换两个值,存值后返回atomic内部原有的值
assert(a.exchange(100) == 10);
assert(a.load() == 100);
assert(a == 100);
system("pause");
return 0;
}
使用mutex,潜在风险是程序中途奔溃,常常使用lock_guard辅助使用mutex,保证mutex 自动析构
mutex未能及时unlock,lock() try_lock_timed() try_lock_until() 是阻塞的,try_lock() 非阻塞,返回bool类型
#define BOOST_THREAD_VERSION 4
#include <boost/thread.hpp>
#include <boost/atomic.hpp>
#include <boost/thread/lockable_adapter.hpp>
#include <boost/thread/lock_factories.hpp>
#include <vector>
#include <iostream>
using namespace std;
using namespace boost;
//account继承lockable_adapter<mutex>,所以account有了mutex的接口,可以像互斥量一样使用
class account : public lockable_adapter<mutex>
{
private:
atomic<int> m_money{ 0 };
public:
account() {}
~account() {}
int sum()const {
return m_money;
}
void withdraw(int x) {
m_money = m_money - x;
}
void deposit(int x) {
m_money += x;
}
};
int main()
{
account a;
{
//unique_lock<Lockable> make_unique_lock(Lockable& mtx);
//unique_lock<Lockable> make_unique_lock(Lockable& mtx,try_to_lock);
auto g = make_unique_lock(a);//无须其他mutex
a.deposit(100);
a.withdraw(20);
assert(a.sum() == 80);
cout << a.sum() << endl;
}
//g 大括号必须加,出了作用于 互斥锁自动解析,否则b ,没法 锁定
{
auto b = make_unique_lock(a, try_to_lock);
if (b)
{
a.withdraw(a.sum());
assert(a.sum() == 0);
cout << a.sum() << endl;
}
}
::system("pause");
return 0;
}
#define BOOST_THREAD_VERSION 4
#include <boost/thread.hpp>
#include <boost/atomic.hpp>
#include <boost/thread/lockable_adapter.hpp>
#include <boost/thread/lock_factories.hpp>
#include <vector>
#include <iostream>
using namespace std;
using namespace boost;
int main()
{
mutex m1, m2;
{
auto g1 = make_unique_lock(m1, adopt_lock);
auto g2 = make_unique_lock(m2, adopt_lock);
//constexpr adopt_lock_t adopt_lock = {}; 编译期 常量标志
//adopt_lock : is_locked = true 不执行锁定操作
lock(m1, m2);//最多5个,锁定2个mutex
//lock() 区别于mutex.lock() 可以一次锁定最多5个mutex
}
//unique_lock 自动解锁
{
auto g1 = make_unique_lock(m1, defer_lock); //推迟锁定
auto g2 = make_unique_lock(m2, defer_lock);
try_lock(g1, g2); //锁定2个unique_lock
}
//unique_lock 自动解锁
::system("pause");
return 0;
}
#define BOOST_THREAD_VERSION 4
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <boost/thread/lockable_adapter.hpp>
#include <boost/thread/lock_factories.hpp>
#include <vector>
#include <iostream>
using namespace std;
using namespace boost;
void dummy(int n)
{
for (int i = 0; i <= n; i++)
cout << "dummy for x " << n << endl;
}
int main()
{
//从某种程度上说,线程就是在进程的另一个空间里运行的一个函数
//因此线程的创建需要传递thread对象一个无惨的可调用物——函数、函数对象、bind/lambda表达式,
//它必须具有operator()以供线程执行
//thread的构造函数使用的是参数的拷贝,因此要求可调用物和参数都是支持拷贝构造
//thread对象 在析构时会调用std::terminate结束线程的执行,并不关心线程是否执行结束
//所以保证线程正确运行,需要调用join() 等待线程执行结束,或者调用detach()分离线程体
//创建thread对象后,会立即执行,不提供start() 或者 begin()方法
thread t1(dummy, 10);
thread t2(dummy, 20);
//cout << t1.get_id() << endl;
//cout << t2.get_id() << endl; //{Not-any-thread}
//assert(t1.get_id() == t2.get_id());
//cout << thread::hardware_concurrency() << endl; //cpu 内核数量
//cout << thread::physical_concurrency() << endl; //真实的物理cpu核心数量
////4个自由函数,无须thread对象即可操作当前线程,
////位于子名称空间boost::this_thread
//boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
if (t1.joinable())
t1.join();
if (t2.joinable())
t2.join();
//bool joinable() 判断thread对象是否标识了一个可执行的线程体,即可调用的函数
//join()阻塞等待线程结束,谁来等!!!主线程
//所以t1 t2依旧如此杂乱
//detach() 分离线程对象和线程体,此后thread对象不代表任何线程体,Joinable() == false
//detach分离,不影响线程执行体继续执行,直到函数结束或者主线程结束
::system("pause");
return 0;
}
看看这凌乱的结果
dummy for x 10
dummy for x 20
dummy for x 10
dummy for x 20dummy for x 10
dummy for x dummy for x 2010
dummy for x dummy for x 2010
dummy for x dummy for x 2010
dummy for x dummy for x 2010
dummy for x dummy for x 2010
dummy for x dummy for x 1020
dummy for x 10dummy for x 20
dummy for x 10dummy for x 20
dummy for x 20
dummy for x 20
dummy for x 20
dummy for x 20
dummy for x 20
dummy for x 20
dummy for x 20
dummy for x 20
dummy for x 20
dummy for x 20
dummy for x 20
分离线程
#define BOOST_THREAD_VERSION 4
#include <boost/thread.hpp>
#include <boost/chrono.hpp>
#include <boost/thread/lockable_adapter.hpp>
#include <boost/thread/lock_factories.hpp>
#include <vector>
#include <iostream>
using namespace std;
using namespace boost;
void dummy(int n)
{
for (int i = 0; i <= n; i++)
cout << "dummy for x " << n << endl;
}
int main()
{
thread t1(dummy, 10);
t1.detach();;
assert(!t1.joinable());
//thread((dummy,100).detach()) 临时线程,执行后自动分离
::system("pause");
return 0;
}