c++并发与同步特性
thread、future、mutex、lock、atomic、memory_order
#include <thread>
#include <chrono>//时间
int threadFun(const char* str)
{
cout<<str<<endl;
return str==nullptr ? 13:14;
}
void thread_create()
{
std::thread t([](){
cout<<"thread start "<<endl;
//sleep(3);
std::this_thread::sleep_for(chrono::seconds(5));
});
cout<<"wait tthread"<<endl;
t.join();
cout<<"tthread finished"<<endl;
//带参线程
std::thread p(threadFun, "zyc");
cout<<"wait pthread"<<endl;
p.join();
cout<<"pthread finished"<<endl;
}
#include <mutex>
//std::lock_guard
class lock_thread final:public thread
{
public:
void start_test(int num)
{
std::lock_guard<std::mutex> lock(m_mtx);
cout<<"start "<<num<<endl;
std::this_thread::sleep_for(chrono::seconds(1));
}
//std::unique_lock
void uinque_test(int num)
{
std::unique_lock<std::mutex> lock(m_uniqueMtx);
cout<<"start "<<num<<endl;
std::this_thread::sleep_for(chrono::seconds(2));
lock.unlock();
std::this_thread::sleep_for(chrono::seconds(1));
lock.lock();
cout<<"restart "<<num<<endl;
std::this_thread::sleep_for(chrono::seconds(3));
}
private:
std::mutex m_mtx;
std::mutex m_uniqueMtx;
};
void lock_guard_test()
{
static lock_thread lthread;//lock_thread lthread();报错——因为不带参数的构造函数,比如lthread()它可以是一个对象,也可是一个函数声明。但是c++编译器总是优先认为是一个函数声明,然后是对象。
lthread.start_test(3);
lthread.start_test(6);
//
std::thread t([](){
lthread.uinque_test(2);
});
std::thread p([](){
lthread.uinque_test(4);
});
t.join();
p.join();
}
//std::future:访问异步操作结果的途径(异步事件完成通知)
#include <future>
void future_test()
{
std::packaged_task<int()> task([](){
//std::this_thread::sleep_for(chrono::seconds(3));
return 8;
});
std::future<int> result = task.get_future();
std::thread(std::move(task)).detach();
//cout<<"waiting... "<<result.get()<<endl;
result.wait();
cout<<"result is "<<result.get()<<endl;
}
/*std::condition_variable:解决互斥操作中需要等待某个条件为真才继续执行,
* 造成的致所有其他线程都无法进入临界区使得条件为真的死锁问题
* 生产者——消费者问题
*/
#include<condition_variable>
#include <queue>
void conditionV()
{
std::queue<int> que;
std::mutex mtx;
std::condition_variable cv;
std::atomic<bool> notified(false);//bool类型-原子操作
auto producer = [&](){
for(int i=0;;++i)
{
std::this_thread::sleep_for(chrono::milliseconds(3000));
std::unique_lock<std::mutex> lock(mtx);
que.emplace(i);
notified = true;
cv.notify_all();
cout<<"producer notify_all"<<endl;
}
};
auto consumer = [&](){
do
{
std::unique_lock<std::mutex> lock(mtx);
while(!notified)
cv.wait(lock);
lock.unlock();
std::this_thread::sleep_for(chrono::milliseconds(2000));//两个消费者,导致消费比生产快
lock.lock();
if(!que.empty())//每次取一个
{
cout<<"consumer pop "<<que.front()<<endl;
que.pop();
}
notified = false;
}while(1);
};
std::thread p(producer);
std::thread c(consumer);
std::thread c1(consumer);
p.join();
c.join();
c1.join();
}
//原子操作——单个线程可能出现指令重排(后面语句先于之前执行)
#include<atomic>
void atomic_test()
{
std::atomic_int atmc(0);
std::thread t([&](){
atmc++;
});
std::thread p([&](){
atmc.fetch_add(2);
});
t.join();
p.join();
cout<<"is support "<<std::boolalpha<<atmc.is_lock_free()<<endl;//std::boolalpha:使bool以true/false字母输出
}
//内存模型:std::memory_order
void memory_order_test()
{
//宽松模型
std::atomic<int> counter = {0};
std::vector<std::thread> vt;
for (int i = 0; i < 100; ++i) {
vt.emplace_back([&](){
counter.fetch_add(1, std::memory_order_relaxed);
});
}
for (auto& t : vt) {
t.join();
}
std::cout << "current counter:" << counter << std::endl;
#if 0
//释放/消费模型
std::atomic<int*> ptr(nullptr);
int v;
std::thread producer([&]() {
int* p = new int(42);
v = 1024;
ptr.store(p, std::memory_order_release);
});
std::thread consumer([&]() {
int* p;
while(!(p = ptr.load(std::memory_order_consume)));
std::cout << "p: " << *p << std::endl;
std::cout << "v: " << v << std::endl;
});
producer.join();
consumer.join();
//释放/获取模型
std::vector<int> v;
std::atomic<int> flag = {0};
std::thread release([&]() {
v.push_back(42);
flag.store(1, std::memory_order_release);
});
std::thread acqrel([&]() {
int expected = 1; // must before compare_exchange_strong
while(!flag.compare_exchange_strong(expected, 2, std::memory_order_acq_rel)) {
expected = 1; // must after compare_exchange_strong
}
// flag has changed to 2
});
std::thread acquire([&]() {
while(flag.load(std::memory_order_acquire) < 2);
std::cout << v.at(0) << std::endl; // must be 42
});
release.join();
acqrel.join();
acquire.join();
//顺序一致模型
std::atomic<int> counter = {0};
std::vector<std::thread> vt;
for (int i = 0; i < 100; ++i) {
vt.emplace_back([&](){
counter.fetch_add(1, std::memory_order_seq_cst);
});
}
for (auto& t : vt) {
t.join();
}
std::cout << "current counter:" << counter << std::endl;
#endif
}