C++11 并发编程
参考书籍: https://chenxiaowei.gitbook.io/c-concurrency-in-action-second-edition-2019/
开启线程
#include <iostream>
#include <thread> // 1
void hello() // 2
{
std::cout << "Hello Concurrent World\n";
}
int main()
{
std::thread t(hello); // 3 创建线程并启动子线程
t.join(); // 4 等待子线程完成
}
-
std::thread::hardware_concurrency()
可以获取CPU核数 -
std::thread::id
线程id ,std::this_thread::get_id()
获取当前线程id
共享数据竞争的问题
多个线程对同一个数据进行写(读)操作
解决办法
互斥量
std::mutex
和std::lock_guard
std::list<int> g_vctNumbers;
std::mutex g_mutex;
void Productor(int nValue)
{
while (1)
{
//std::lock_guard<std::mutex> guard(g_mutex);
std::scoped_lock scopelock(g_mutex);
g_vctNumbers.push_back(nValue);
}
}
bool Consumer()
{
bool bFlag = false;
while (1)
{
//std::lock_guard<std::mutex> guard(g_mutex);
std::scoped_lock scopelock(g_mutex);
if(g_vctNumbers.size() > 0)
g_vctNumbers.pop_back();
}
return bFlag;
}
int main()
{
std::vector<std::thread> vctThds;
//std::thread t1( AddItem, 10);
//std::thread t2( FindItem, 10);
//不能 先创建线程, 然后 push_back
vctThds.emplace_back( Productor, 10 );
vctThds.emplace_back( Consumer );
for (auto &t : vctThds)
{
t.join();
}
std::cout << "hello world" << std::endl;
system("pause");
return 0;
}
死锁即解决方案
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
using namespace std;
struct some_big_object
{
std::string strName;
std::string strAddr;
int nNo;
};
void swap(some_big_object& lhs, some_big_object& rhs)
{
some_big_object tmp;
tmp.nNo = lhs.nNo;
tmp.strAddr = lhs.strAddr;
tmp.strName = lhs.strName;
lhs.nNo = rhs.nNo;
lhs.strAddr = rhs.strAddr;
lhs.strName = rhs.strName;
rhs.nNo = tmp.nNo;
rhs.strAddr = tmp.strAddr;
rhs.strName = tmp.strName;
}
class X
{
//public:
private:
some_big_object some_detail;
std::mutex m;
public:
X(some_big_object const& sd) :some_detail(sd) {}
#if 0
friend void swap(X& lhs, X& rhs)
{
if (&lhs == &rhs)
return;
//传统方式: 手动管理
std::cout << "starting lock two mutex" << std::endl;
lhs.m.lock();
rhs.m.lock();
std::cout << "lock two mutex successed" << std::endl;
swap(lhs.some_detail, rhs.some_detail);
lhs.m.unlock();
rhs.m.unlock();
std::cout << "swaped successed." << std::endl;
}
#elif 0
friend void swap(X& lhs, X& rhs)
{
if (&lhs == &rhs)
return;
std::cout << "starting lock two mutex" << std::endl;
std::lock(lhs.m, rhs.m); // 锁住两个互斥量
std::cout << "lock two mutex successed" << std::endl;
//将互斥量交由 std::lock_guard 来管理(释放锁)
std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock); // 2
std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock); // 3
swap(lhs.some_detail, rhs.some_detail);
std::cout << "swaped successed." << std::endl;
}
#else
friend void swap(X& lhs, X& rhs)
{
if (&lhs == &rhs)
return;
std::cout << "starting lock two mutex" << std::endl;
//在C++17中, 使用 scoped_lock 管理多个互斥量
//构造即初始化(上锁)
//析构时释放(解锁)
std::scoped_lock scopedlock(lhs.m, rhs.m); //C++17
swap(lhs.some_detail, rhs.some_detail);
std::cout << "swaped successed." << std::endl;
}
#endif
friend std::ostream& operator << (std::ostream &outs, const X & x)
{
outs << "name:" << x.some_detail.strName << "; addr : "
<< x.some_detail.strAddr << "; no:" << x.some_detail.nNo;
return outs;
}
}
int main()
{
X a(some_big_object{"ZhangSan", "BeiJing", 9});
X b(some_big_object{"LiSi", "NanJing", 100});
//a.m.lock();
#if 0
swap(a, b);
#else
std::cout << "before swap: " << std::endl;
std::cout << "a ---> " << a << std::endl;
std::cout << "b ---> " << b << std::endl;
auto func = [&a , &b]() {
while (1)
{
swap(a, b);
}
};
std::vector<std::thread> vctThds;
for (int i = 0; i < std::thread::hardware_concurrency(); i++)
{
vctThds.emplace_back( func );
}
for (auto &thrd : vctThds)
{
thrd.join();
}
#endif
std::cout << "after swaped: " << std::endl;
std::cout << "a ---> " << a << std::endl;
std::cout << "b ---> " << b << std::endl;
std::cout << "hello world" << std::endl;
system("pause");
return 0;
}
/**
*Date: 2020/02/02 18:04
*Author:yqq
*Descriptions:none
*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <cstdio>
#include <iostream>
#include <atomic>
using namespace std;
int main(void)
{
std::atomic_flag atom_flag;// = ATOMIC_FLAG_INIT;
if (!atom_flag.test_and_set(std::memory_order_acquire))
{
std::cout << "setted" << std::endl;
}
else
{
//if (atom_flag.test_and_set(std::memory_order_acquire)) //error
atom_flag.clear();
if (!atom_flag.test_and_set(std::memory_order_acquire))
{
std::cout << "setted" << std::endl;
}
std::cout << "not setted" << std::endl;
}
std::atomic<bool> bFlag = false;
bool bExpected = true;
bFlag.compare_exchange_strong( bExpected, false); //如果bFlag当前的值与bExpected不同, 则将
std::cout << ((bFlag) ? ("true") : ("false") )<< std::endl;
std::cout << "hello world" << std::endl;
return 0;
}
/**
*Date: 2020/02/04 17:47
*Author:yqq
*Descriptions:none
*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <cstdio>
#include <iostream>
#include <atomic>
#include <thread>
using namespace std;
int main(void)
{
int a = 99;
int* pa = &a ;
std::atomic<int*> atomicPtr(pa);
std::cout << * atomicPtr.load() << std::endl;
int b = 55;
atomicPtr.store( &b );
std::cout << * atomicPtr.load() << std::endl;
if (atomicPtr.is_lock_free())
{
std::cout << "is lock_free" << std::endl;
}
else
{
std::cout << "is not lock free" << std::endl;
}
//atomicPtr.fetch_add();
int nArr[100]{0};
for (int i = 0; i < sizeof(nArr) / sizeof(nArr[0]); i++)
{
nArr[i] = i * 10;
}
std::atomic<int*> pArr( nArr );
int* pTmp = pArr.fetch_add(3); // 先返回pArr 在 += 3
std::cout << *pTmp << std::endl;
std::cout << *pArr.load() << std::endl;
std::cout << "hello world" << std::endl;
return 0;
}
/*
使用 std::call_once 和 std::once_flag 解决资源初始化多线程竞争问题
*/
#include <iostream>
#include <thread>
#include <mutex>
#include <string>
#include <chrono>
#include <vector>
#include <sstream>
using namespace std;
struct Printer
{
private:
std::once_flag __m_initFlag;
void Init()
{
std::cout << "starting init printer" << std::endl;
std::cout << "init finished." << std::endl;
}
public:
void Print( const std::string &strInput)
{
std::call_once( __m_initFlag, &Printer::Init, this );
for(int i = 0; i < 10; i++)
{
std::ostringstream fmts;
std::thread::id tid = std::this_thread::get_id();
fmts << "thread " << std::this_thread::get_id() << "'s i is " << i << strInput;
std::this_thread::sleep_for( std::chrono::microseconds(50) );
std::cout << fmts.str() << std::endl;
}
}
};
#if 0
int main()
{
Printer p;
// p.Print("hello");
std::vector<std::thread> vctThds;
for(int i = 0; i < 4; i++)
{
//std::thread t1( &Printer::Print, &p, "thread2" );
vctThds.emplace_back( &Printer::Print, &p, "");
}
for(auto &t : vctThds)
{
if(t.joinable())
t.join();
}
/*
std::thread t2( &Printer::Print, &p, "thread3" );
if(t1.joinable())
t1.join();
if(t2.joinable())
t2.join();
*/
return 0;
}
#endif
#include <iostream>
#include <list>
#include <random>
#include <algorithm>
#include <future>
#include <thread>
#include <chrono>
template<typename T>
std::list<T> parallel_quick_sort(std::list<T> input)
{
if(input.empty())
{
return input;
}
std::list<T> result;
result.splice(result.begin(),input,input.begin());
T const& pivot=*result.begin();
auto divide_point=std::partition(input.begin(),input.end(),
[&](T const& t){return t<pivot;});
std::list<T> lower_part;
lower_part.splice(lower_part.end(),input,input.begin(),
divide_point);
std::future<std::list<T> > new_lower( // 1
std::async(¶llel_quick_sort<T>,std::move(lower_part)));
auto new_higher(
parallel_quick_sort(std::move(input))); // 2
result.splice(result.end(),new_higher); // 3
result.splice(result.begin(),new_lower.get()); // 4
return result;
}
#if 0
int main()
{
//std::default_random_engine generator;
std::mt19937 generator;
//std::random_device generator; //不确定的随机数生成器
std::uniform_int_distribution<int> distribution(-10000, 10000);
std::list<int> lstNumbers;
for(int i = 0; i < 1000; i++)
{
lstNumbers.emplace_back( distribution(generator) );
}
auto startTime = std::chrono::high_resolution_clock::now();
auto lstSorted = parallel_quick_sort<int>(lstNumbers);
auto endTime = std::chrono::high_resolution_clock::now();
std::cout << "elasped time: " << (endTime - startTime).count() << std::endl;
//std::cout << std::chrono::duration_cast<std::chrono::seconds>((endTime - startTime).count()) << std::endl;
for(auto &item : lstSorted)
{
std::cout << item << "\t";
}
std::cout << std::endl;
return 0;
}
#endif
#include <iostream>
#include <thread>
#include <queue>
#include <memory>
#include <mutex>
#include <condition_variable>
#include <string>
#include <sstream>
#include <chrono>
#include <atomic>
using namespace std;
template<typename T>
class threadsafe_queue
{
private:
mutable std::mutex mut; // 1 互斥量必须是可变的
std::queue<T> data_queue;
std::condition_variable data_cond;
public:
threadsafe_queue()
{}
threadsafe_queue(threadsafe_queue const& other)
{
std::lock_guard<std::mutex> lk(other.mut);
data_queue=other.data_queue;
}
void push(T new_value)
{
std::lock_guard<std::mutex> lk(mut);
data_queue.push(new_value);
data_cond.notify_one();
}
/**
* wait()会去检查这些条件(通过调用所提供的lambda函数),
* 当条件满足(lambda函数返回true)时返回。如果条件不满足(lambda函数返回false),
* wait()函数将解锁互斥量,并且将这个线程(上段提到的处理数据的线程)置于阻塞或等待状态。
* 当准备数据的线程调用notify_one()通知条件变量时,处理数据的线程从睡眠状态中苏醒,
* 重新获取互斥锁,并且再次检查条件是否满足。在条件满足的情况下,从wait()返回并继续持有锁;
* 当条件不满足时,线程将对互斥量解锁,并且重新开始等待。这就是为什么用std::unique_lock而
* 不使用std::lock_guard——等待中的线程必须在等待期间解锁互斥量,并在这之后对互斥量再次上锁,
* 而std::lock_guard没有这么灵活。如果互斥量在线程休眠期间保持锁住状态,
* 准备数据的线程将无法锁住互斥量,也无法添加数据到队列中;同样的,等待线程也永远不会知道条件何时满足。
*/
void wait_and_pop(T& value)
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[this]{return !data_queue.empty();});
value=data_queue.front();
data_queue.pop();
}
std::shared_ptr<T> wait_and_pop()
{
std::unique_lock<std::mutex> lk(mut);
data_cond.wait(lk,[this]{return !data_queue.empty();});
std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
data_queue.pop();
return res;
}
bool try_pop(T& value)
{
std::lock_guard<std::mutex> lk(mut);
if(data_queue.empty())
return false;
value=data_queue.front();
data_queue.pop();
return true;
}
std::shared_ptr<T> try_pop()
{
std::lock_guard<std::mutex> lk(mut);
if(data_queue.empty())
return std::shared_ptr<T>();
std::shared_ptr<T> res(std::make_shared<T>(data_queue.front()));
data_queue.pop();
return res;
}
bool empty() const
{
std::lock_guard<std::mutex> lk(mut);
return data_queue.empty();
}
};
#if 0
int main()
{
threadsafe_queue<std::string> q;
// std::condition_variable condvarFinished;
//std::atomic_flag finishedFlag(false);
std::atomic_bool finishedFlag = false;
std::thread t1([&](){
for(int i = 0; i < 1000; i++){
std::ostringstream fmts;
fmts << "this is " << i;
std::this_thread::sleep_for( std::chrono::microseconds( 10 ) );
std::cout << "push " << i << std::endl;
q.push(fmts.str());
}
finishedFlag = true;
std::cout << "productor finished..." << std::endl;
});
std::thread t2([&](){
while(!finishedFlag){
std::string strTmp = "";
q.wait_and_pop(strTmp);
std::cout << "got :" << strTmp << std::endl;
}
std::cout << "consumer finished..." << std::endl;
});
if(t1.joinable())
t1.join();
if(t2.joinable())
t2.join();
return 0;
}
#endif
// CPP11Concurency.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <thread>
#include <chrono>
void thread_proc()
{
for (int i = 0; i < 10; i++)
{
std::cout << "thread :" << std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for( std::chrono::microseconds(10) );
}
}
struct Functor
{
char* m_pEchoStr = nullptr;
void operator()()
{
for (int i = 0; i < 10; i++)
{
sprintf(m_pEchoStr, "ehco : %d", i);
std::cout << "Functor :" << std::this_thread::get_id() << " echo str:" << m_pEchoStr << std::endl;
std::this_thread::sleep_for(std::chrono::microseconds(10));
}
}
};
int main()
{
//1.通过普通函数, 作为thread的构造函数参数, 创建线程
std::thread t1(thread_proc); //创建并立即启动线程
//t1.join();
t1.detach();
if (!t1.joinable()) //如果线程已经detach, 则joinable为false
{
std::cout << "can't join thread " << t1.get_id() << std::endl;
}
//2.使用仿函数(函数对象) 作为thread构造函数参数, 创建线程
//int n = 999999999;
//std::string strTmp("hello world");
//functor.m_pEchoStr = strTmp.c_str();
char szBuf[1024] = "hello world";
Functor functor;
functor.m_pEchoStr = szBuf;
std::thread t2(functor);
t2.join();
//t2.detach(); //!!!!特别注意: detach 需要注意 线程参数的生命周期, 否则会发生不可预料的错误
//3.使用lambda函数作为thread构造函数的参数, 创建线程
std::thread t3([&]() {
for (int i = 0; i < 5; i++)
{
sprintf(szBuf, "this is lamdba %d", i);
std::cout << "lambda : " << i << " ------>" << szBuf << std::endl;;
}
});
t3.join();
std::cout << "Hello World!\n";
}
#include <condition_variable>
#include <mutex>
#include <chrono>
#include <iostream>
#include <thread>
std::condition_variable cv;
bool done = false;
std::mutex m;
void worker()
{
for(int i = 0; i < 10; i++)
{
std::this_thread::sleep_for( std::chrono::milliseconds(300) );
cv.notify_all(); //通知所有
//cv.notify_one();
}
done = true;
}
bool wait_loop()
{
auto const timeout= std::chrono::steady_clock::now()+
std::chrono::milliseconds(500);
std::unique_lock<std::mutex> lk(m);
while(!done)
{
std::cv_status cvStatus = cv.wait_until( lk, timeout );
if(std::cv_status::timeout == cvStatus)
{
std::cout << std::this_thread::get_id() << " timeout" << std::endl;
break;
}
else if(std::cv_status::no_timeout == cvStatus)
{
std::cout << "waited condition_variable" << std::endl;
break;
}
else{}
}
return done;
}
#if 0
int main()
{
//wait_loop();
std::thread t1( wait_loop );
std::thread t11( wait_loop );
std::thread t111( wait_loop );
std::thread t2( worker );
t1.join();
t11.join();
t111.join();
t2.join();
return 0;
}
#endif
#include <functional>
#include <iostream>
#include <string>
#include <map>
int add(int a, int b)
{
return a + b;
}
int mul(int a, int b)
{
return a * b;
}
#if 0
int main()
{
auto fn = std::function<int(int, int)>(add);
std::map<std::string, decltype(fn) > mapFns;
mapFns.insert( std::make_pair( "+", fn ));
mapFns.insert( std::make_pair("*", std::function (mul)) );
mapFns.insert( std::make_pair("-", [](int a, int b) -> int{
return a - b;
}) );
std::cout << mapFns["*"](6, 9) << std::endl; //54
std::cout << mapFns["+"](6, 9) << std::endl; //15
std::cout << mapFns["-"](6, 9) << std::endl; //-3
return 0;
}
#endif
#include <iostream>
#include <future>
#include <thread>
#include <string>
#include <memory>
#include <chrono>
#include <cmath>
using namespace std;
double square_root(double x)
{
if(x<0)
{
throw std::out_of_range("x<0");
}
return sqrt(x);
}
#if 0
int main()
{
/**
* launch::async表示开启一个新的线程执行fn
launch::deferred 表示fn推迟到future::wait/get时才执行
launch::async|launch::deferred表示由库自动选择哪种机制执行fn,和第一种构造方式async(fn,args)策略相同
*/
std::future<double> f=std::async(square_root, 9);
std::cout << "doing other things..." << std::endl;
for(int i = 0; i < 1000; i++)
{
std::cout << "other thing" << std::endl;
}
double y = f.get();
std::cout << "reuslt = " << y << std::endl;
return 0;
}
#endif
/**
* packaged_task 和 std::function 很像
*
*/
// packaged_task example
#include <iostream> // std::cout
#include <future> // std::packaged_task, std::future
#include <chrono> // std::chrono::seconds
#include <thread> // std::thread, std::this_thread::sleep_for
// count down taking a second for each value:
int countdown (int from, int to)
{
for (int i=from; i!=to; --i) {
std::cout << i << '\n';
std::this_thread::sleep_for(std::chrono::seconds(1));
}
std::cout << "Lift off!\n";
return from-to;
}
#if 0
int main ()
{
std::packaged_task<int(int,int)> tsk (countdown); // set up packaged_task
std::future<int> ret = tsk.get_future(); // get future
std::thread th (std::move(tsk),10,0); // spawn thread to count down from 10 to 0
// ...
int value = ret.get(); // wait for the task to finish and get result
std::cout << "The countdown lasted for " << value << " seconds.\n";
th.join();
return 0;
}
#endif
/*
#include <iostream> // std::cout
#include <functional> // std::ref
#include <thread> // std::thread
#include <future> // std::promise, std::future
void print_int(std::future<int>& fut)
{
int x = fut.get(); // 获取共享状态的值.
std::cout << "value: " << x << '\n'; // 打印 value: 10.
}
int main ()
{
std::promise<int> prom; // 生成一个 std::promise<int> 对象.
std::future<int> fut = prom.get_future(); // 和 future 关联.
std::thread t(print_int, std::ref(fut)); // 将 future 交给另外一个线程t.
prom.set_value(10); // 设置共享状态的值, 此处和线程t保持同步.
t.join();
return 0;
}
*/
/*
#include <iostream> // std::cin, std::cout, std::ios
#include <functional> // std::ref
#include <thread> // std::thread
#include <future> // std::promise, std::future
#include <exception> // std::exception, std::current_exception
void get_int(std::promise<int>& prom)
{
int x;
std::cout << "Please, enter an integer value: ";
std::cin.exceptions (std::ios::failbit); // throw on failbit
try
{
std::cin >> x; // sets failbit if input is not int
prom.set_value(x);
}
catch (std::exception&)
{
prom.set_exception(std::current_exception());
}
}
void print_int(std::future<int>& fut)
{
try {
int x = fut.get();
std::cout << "value: " << x << '\n';
} catch (std::exception& e) {
std::cout << "[exception caught: " << e.what() << "]\n";
}
}
int main ()
{
std::promise<int> prom;
std::future<int> fut = prom.get_future();
std::thread th1(get_int, std::ref(prom));
std::thread th2(print_int, std::ref(fut));
th1.join();
th2.join();
return 0;
}
*/
#include <iostream> // std::cin, std::cout, std::ios
#include <functional> // std::ref
#include <thread> // std::thread
#include <future> // std::promise, std::future
#include <exception> // std::exception, std::current_exception
/*
int main()
{
std::thread t1();
return 0;
}
*/
#include <iostream>
#include <list>
#include <random>
#include <algorithm>
#include <thread>
#include <chrono>
template<typename T>
std::list<T> sequential_quick_sort(std::list<T> input)
{
if(input.empty())
{
return input;
}
std::list<T> result;
result.splice(result.begin(),input,input.begin()); // 1
T const& pivot=*result.begin(); // 2
auto divide_point=std::partition(input.begin(),input.end(),
[&](T const& t){return t<pivot;}); // 3
std::list<T> lower_part;
lower_part.splice(lower_part.end(),input,input.begin(), divide_point); // 4
auto new_lower( sequential_quick_sort(std::move(lower_part))); // 5
auto new_higher(sequential_quick_sort(std::move(input))); // 6
result.splice(result.end(),new_higher); // 7
result.splice(result.begin(),new_lower); // 8
return result;
}
#if 0
int main()
{
//std::default_random_engine generator;
std::mt19937 generator;
//std::random_device generator; //不确定的随机数生成器
std::uniform_int_distribution<int> distribution(-10000, 10000);
std::list<int> lstNumbers;
for(int i = 0; i < 1000; i++)
{
lstNumbers.emplace_back( distribution(generator) );
}
auto startTime = std::chrono::high_resolution_clock::now();
auto lstSorted = sequential_quick_sort<int>(lstNumbers);
auto endTime = std::chrono::high_resolution_clock::now();
std::cout << "elasped time: " << (endTime - startTime).count() << std::endl;
//std::cout << std::chrono::duration<double, std::chrono::seconds> (endTime - startTime).count() << std::endl;
for(auto &item : lstSorted)
{
std::cout << item << "\t";
}
std::cout << std::endl;
return 0;
}
#endif
/**
*Date: 2020/02/04 19:01
*Author:yqq
*Descriptions:
1.多个线程可以读写不同shared_ptr(副本)(即使shared_ptr指向同一个对象)
2.多个线程可以读取同一个 shared_ptr
3.多个线程不能写同一个shared_ptr , 除非使用 原子函数, 如: std::atomic_load std::atomic_store
*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <cstdio>
#include <iostream>
#include <atomic>
#include <thread>
#include <memory>
#include <chrono>
#include <vector>
using namespace std;
struct Printer
{
int m_nA = 0;
Printer(int a) : m_nA(a)
{
}
void Show()
{
//std::this_thread::sleep_for( std::chrono::microseconds(100) );
std::cout << "thread " << std::this_thread::get_id() << " m_nA: " << m_nA << std::endl;
std::cout << this << std::endl;
this->m_nA = 99;
}
};
std::shared_ptr<Printer> g_Data;
void ProcessGlobalData()
{
while (nullptr == g_Data);
//for (int i = 0; i < 10; i++)
while(1)
{
//shared_ptr<Printer> spData = std::atomic_load( &g_Data);
shared_ptr<Printer> spData = g_Data;
spData->Show();
}
}
#if 0
void UpdateGlobalData()
{
for (int i = 0; i < 10; i++)
{
std::this_thread::sleep_for( std::chrono::microseconds(1) );
std::shared_ptr<Printer> spTmp = std::make_shared<Printer>( i );
std::atomic_store( &g_Data, spTmp );
}
}
#endif
#if 0
//多个线程读取同一个 shared_ptr
void UpdateGlobalData()
{
std::shared_ptr<Printer> spTmp = std::make_shared<Printer>(9999);
g_Data = spTmp;
for (int i = 0; ; )
{
std::this_thread::sleep_for(std::chrono::microseconds(1));
spTmp->m_nA = i;
}
}
#endif
//多个线程写同一个 shared_ptr
void UpdateGlobalData()
{
//std::shared_ptr<Printer> spTmp = std::make_shared<Printer>(9999);
for (int i = 0; ; )
{
//g_Data = spTmp;
if (nullptr == g_Data)
{
std::shared_ptr<Printer> spTmp =
g_Data = std::make_shared<Printer>(9999);
}
std::cout << "hello" << std::endl;
g_Data->Show();
}
}
//多个线程写同一个 shared_ptr
void UpdateGlobalDataToNullptr()
{
for (int i = 0; ; )
{
g_Data = nullptr;
}
}
int main(void)
{
std::vector<std::thread> vctThreads;
#if 0
vctThreads.emplace_back( UpdateGlobalData );
//多个线程读取同一个 shared_ptr
vctThreads.emplace_back( ProcessGlobalData );
vctThreads.emplace_back( ProcessGlobalData );
vctThreads.emplace_back( ProcessGlobalData );
vctThreads.emplace_back( ProcessGlobalData );
#endif
vctThreads.emplace_back( UpdateGlobalData );
vctThreads.emplace_back( UpdateGlobalData );
vctThreads.emplace_back( UpdateGlobalData );
vctThreads.emplace_back( UpdateGlobalData );
vctThreads.emplace_back( UpdateGlobalDataToNullptr );
for (auto& thd : vctThreads)
{
thd.join();
}
std::cout << "hello world" << std::endl;
return 0;
}
/**
* 2020-01-31
*
* 如果只有一个全局变量 , 直接使用 static就可以解决初始化竞争的问题,
*
* 注意: 仅仅是解决 "初始化竞争", 而不能解决初始化后的 "资源竞争"
*
*
*/
#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <mutex>
#include <chrono>
#include <string>
class MySingleton
{
protected:
MySingleton(){}
~MySingleton() {}
public:
void Print()
{
std::cout << this << std::endl;
std::cout << "this is singleton pattern" << std::endl;
}
/*virtual void ~Print()
{
std::cout << "~Print()" << std::endl;
}*/
static MySingleton * GetInstance()
{
/*
static MySingleton *pInstance = nullptr;
if(nullptr == pInstance)
{
pInstance = new MySingleton();
}
return pInstance;
*/
//参考: https://chenxiaowei.gitbook.io/c-concurrency-in-action-second-edition-2019/3.0-chinese/3.3-chinese
//在C++11后, 此过程是线程安全的. 所以不必再使用互斥量
static MySingleton *pInstance = new MySingleton();
return pInstance;
}
};
#if 0
int main()
{
std::cout << "new debug" << std::endl;
MySingleton *pInst = MySingleton::GetInstance();
MySingleton *pInst2 = MySingleton::GetInstance();
pInst->Print();
pInst2->Print();
return 0;
}
#endif
/**
* 模板偏特化
*/
#include <iostream>
using namespace std;
template<typename T1,typename T2>
class Test
{
public:
Test(T1 i,T2 j):a(i),b(j){cout<<"模板类"<<endl;}
private:
T1 a;
T2 b;
};
//必须有 上面泛化 才能有下面的 偏特化
template<typename T1,typename T2> //这是范围上的偏特化
class Test<T1*,T2*>
{
public:
Test(T1* i,T2* j):a(i),b(j){cout<<"指针偏特化"<<endl;}
private:
T1* a;
T2* b;
};
/*
int main()
{
return 0;
}
*/
// splicing lists
#include <iostream>
#include <list>
#if 0
int main ()
{
std::list<int> mylist1, mylist2;
std::list<int>::iterator it;
// set some initial values:
for (int i=1; i<=4; ++i)
mylist1.push_back(i); // mylist1: 1 2 3 4
for (int i=1; i<=3; ++i)
mylist2.push_back(i*10); // mylist2: 10 20 30
it = mylist1.begin();
++it; // points to 2
mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4
// mylist2 (empty)
// "it" still points to 2 (the 5th element)
mylist2.splice (mylist2.begin(),mylist1, it);
// mylist1: 1 10 20 30 3 4
// mylist2: 2
// "it" is now invalid.
it = mylist1.begin();
std::advance(it,3); // "it" points now to 30
mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end());
// mylist1: 30 3 4 1 10 20
std::cout << "now *it = " << *it << std::endl;
std::cout << "mylist1 contains:";
for (it=mylist1.begin(); it!=mylist1.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
std::cout << "mylist2 contains:";
for (it=mylist2.begin(); it!=mylist2.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
return 0;
}
#endif
#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <mutex>
#include <chrono>
#include <string>
using namespace std;
struct some_big_object
{
std::string strName;
std::string strAddr;
int nNo;
};
void swap(some_big_object& lhs, some_big_object& rhs)
{
some_big_object tmp;
tmp.nNo = lhs.nNo;
tmp.strAddr = lhs.strAddr;
tmp.strName = lhs.strName;
lhs.nNo = rhs.nNo;
lhs.strAddr = rhs.strAddr;
lhs.strName = rhs.strName;
rhs.nNo = tmp.nNo;
rhs.strAddr = tmp.strAddr;
rhs.strName = tmp.strName;
}
class X
{
private:
some_big_object some_detail;
std::mutex m;
public:
X(some_big_object const& sd) :some_detail(sd) {}
#if 0
friend void swap(X& lhs, X& rhs)
{
if (&lhs == &rhs)
return;
//传统方式: 手动管理
std::cout << "starting lock two mutex" << std::endl;
lhs.m.lock();
rhs.m.lock();
std::cout << "lock two mutex successed" << std::endl;
swap(lhs.some_detail, rhs.some_detail);
lhs.m.unlock();
rhs.m.unlock();
std::cout << "swaped successed." << std::endl;
}
#elif 0
friend void swap(X& lhs, X& rhs)
{
if (&lhs == &rhs)
return;
std::cout << "starting lock two mutex" << std::endl;
std::lock(lhs.m, rhs.m); // 锁住两个互斥量
std::cout << "lock two mutex successed" << std::endl;
//将互斥量交由 std::lock_guard 来管理(释放锁)
std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock); // 2
std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock); // 3
swap(lhs.some_detail, rhs.some_detail);
std::cout << "swaped successed." << std::endl;
}
#elif 0
friend void swap(X& lhs, X& rhs)
{
if (&lhs == &rhs)
return;
std::cout << "starting lock two mutex" << std::endl;
//在C++17中, 使用 scoped_lock 管理多个互斥量
//构造即初始化(上锁)
//析构时释放(解锁)
std::scoped_lock scopedlock(lhs.m, rhs.m); //C++17
swap(lhs.some_detail, rhs.some_detail);
std::cout << "swaped successed." << std::endl;
}
#else
friend void swap(X& lhs, X& rhs)
{
if (&lhs == &rhs)
return;
std::cout << "starting lock two mutex" << std::endl;
//
std::unique_lock<std::mutex> lock_a( lhs.m, std::defer_lock );
std::unique_lock<std::mutex> lock_b( rhs.m, std::defer_lock );
std::lock( lock_a, lock_b );
swap(lhs.some_detail, rhs.some_detail);
std::cout << "swaped successed." << std::endl;
}
#endif
friend std::ostream& operator << (std::ostream &outs, const X & x)
{
outs << "name:" << x.some_detail.strName << "; addr : "
<< x.some_detail.strAddr << "; no:" << x.some_detail.nNo;
return outs;
}
};
#if 0
int main()
{
X a(some_big_object{"ZhangSan", "BeiJing", 9});
X b(some_big_object{"LiSi", "NanJing", 100});
//a.m.lock();
#if 0
swap(a, b);
#else
std::cout << "before swap: " << std::endl;
std::cout << "a ---> " << a << std::endl;
std::cout << "b ---> " << b << std::endl;
auto func = [&a , &b]() {
//while (1)
for(int i = 0; i < 10000; i++)
{
std::this_thread::sleep_for( std::chrono::microseconds(10) );
swap(a, b);
}
};
std::vector<std::thread> vctThds;
for (int i = 0; i < std::thread::hardware_concurrency(); i++)
{
vctThds.emplace_back( func );
}
for (auto &thrd : vctThds)
{
thrd.join();
}
#endif
std::cout << "after swaped: " << std::endl;
std::cout << "a ---> " << a << std::endl;
std::cout << "b ---> " << b << std::endl;
std::cout << "hello world" << std::endl;
system("pause");
return 0;
}
#endif
/**
*Date: 2020/01/11 15:28
*Author:yqq
*Descriptions: c++11 thread ����
*/
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <cstdio>
#include <iostream>
#include <thread>
#include <string>
using namespace std;
void MyPrintThreadProc(int n, const char *pszTmp)
{
std::cout << "n" << n << "str: " << pszTmp;
}
int main(void)
{
const char *pszTmp = "hwllo";
int n = 999;
std::thread t1(MyPrintThreadProc, n, pszTmp);
t1.join();
std::cout << "hello world" << std::endl;
return 0;
}