1.线程不锁,导致最终获取数据不对
int sum = 0;
mutex mu;
void A()
{
for (int i=0;i<100000;++i)
{
sum++;
}
cout << "a is :" << sum << endl;
}
int main()
{
thread a(A);
thread b(A);
thread c(A);
a.join();
b.join();
c.join();
cout << "父线程" << endl;
cout << "a is :" << sum << endl;
return 0;
}
2.线程加mutex锁,方法:对数据采用lock()和unlock()方法成对出现
void A()
{
for (int i=0;i<100000;++i)
{
mu.lock();
sum++;
mu.unlock();
}
cout << "a is :" << sum << endl;
}
3.lock()和unlock(),有两个问题:
1.写两个太麻烦
2.如果在lock过程抛出异常会导致死锁
采用的方法是用lock_guard
void A()
{
for (int i=0;i<100000;++i)
{
lock_guard lockmu(mu);
sum++;
}
cout << "a is :" << sum << endl;
}
4.当有两个锁锁数据的时候,如果调用顺序不同会产生死锁,在A中顺序是a,b,在B中顺序是b,a
会导致程序死锁。
int sum = 0;
mutex mu;
mutex mu2;
void A()
{
for (int i=0;i<100000;++i)
{
lock_guard lockmu(mu);
sum++;
lock_guard lockmu2(mu2);
sum++;
}
cout << "a is :" << sum << endl;
}
void B()
{
for (int i = 0; i < 100000; ++i)
{
lock_guard lockmu2(mu2);
sum++;
lock_guard lockmu(mu);
sum++;
}
cout << "a is :" << sum << endl;
}
int main()
{
thread a(A);
thread b(B);
a.join();
b.join();
cout << "父线程" << endl;
cout << "a is :" << sum << endl;
return 0;
}
5.解决的办法是采用lock开始就规定好锁的顺序,并在每个锁中加入adopt_lock适配lock的参数,可以保证锁的顺序。
int sum = 0;
mutex mu;
mutex mu2;
void A()
{
for (int i=0;i<100000;++i)
{
lock(mu, mu2);
lock_guard lockmu(mu,adopt_lock);
sum++;
lock_guard lockmu2(mu2, adopt_lock);
sum++;
}
cout << "a is :" << sum << endl;
}
void B()
{
for (int i = 0; i < 100000; ++i)
{
lock(mu, mu2);
lock_guard lockmu2(mu2, adopt_lock);
sum++;
lock_guard lockmu(mu, adopt_lock);
sum++;
}
cout << "a is :" << sum << endl;
}
int main()
{
thread a(A);
thread b(B);
a.join();
b.join();
cout << "父线程" << endl;
cout << "a is :" << sum << endl;
return 0;
}
6.和lock_guard相对的还有一个更灵活的锁unique_lock,
unique_lock优点:
1.在lock_guard的范围下,所有代码都被锁住,而unique_lock范围下,如果不加参数(defer_lock),效果如下:
2.unique_lock可以通过move函数转移控制权,而lock_guard不行。
unique_lock缺点:
消耗更多性能。
7.多线程的call_once的使用
转载:C++11中的std::call_once_爱很遥远-CSDN博客
8.条件变量condition_variable使用
主要要点:在于相当于在全局设置了一个记录器,被触发一次,就会记录一次,然后要用的时候就减一次。
转载:C++-----------notify_one()与notify_all()_1.01的博客-CSDN博客
condition_variable cv; mutex mu; vectorsum; void A() { for (int i = 0; i < 10; ++i) { unique_lock locker(mu); cv.notify_one(); sum.emplace_back(i); cout << "sum is:" << i << endl; } } void B() { int data = 0; while (data!=9) { unique_lock locker(mu); cv.wait(locker, []() {return sum.size()!=0; }); data = sum[0]; sum.erase(sum.begin()); cout << "data is:" << data << endl; } } int main() { thread a(A); thread b(B); a.join(); b.join(); cout << "父线程" << endl; return 0; }
9.异步线程future和 async、promise
1.std::promise 是C++11并发编程中常用的一个类,常配合std::future使用。
在两个线程中,promise p,future f=p.get_future, 两个线程同时启动,当遇到f.get(),如果另一个线程不给p设置值,f就会一直阻塞,等待,线程p中被设置了值,才继续下去
多线程笔记一 future和async的使用_qq_1410888563的博客-CSDN博客
void A(promise&p) { cout << "1:" << endl; p.set_value(10); cout << "3:" << endl; int a = 20; a = a * 10; cout << "data is:" <& f) { cout << "2:" << endl; int data =f.get(); cout << "data is:" << data < pro; future fu = pro.get_future(); thread a(A,ref(pro)); thread b(B,ref(fu)); a.join(); b.join(); cout << "父线程" << endl; return 0; }
10.packaged-task
主要作用:使代码更加简洁
int A(int a, int& b)
{
b += 10;
return a + b;
}
int main()
{
packaged_task t(A);
future f = t.get_future();
int num = 10;
thread a(move(t),10, ref(num));
a.join();
int b= f.get();
cout << "b is :" <
11.时间限制4种类型方法
int main()
{
thread t(A);
this_thread::sleep_for(chrono::milliseconds(3));
chrono::steady_clock::time_point tp = chrono::steady_clock::now() + chrono::microseconds(4);
this_thread::sleep_until(tp);
mutex mu;
unique_lock locker(mu);
locker.try_lock_for(chrono::microseconds(3));
locker.try_lock_until(tp);
condition_variable cond;
cond.wait_for(locker,chrono::microseconds(3));
cond.wait_until(locker, tp);
promise p;
future f = p.get_future();
f.wait_for(chrono::microseconds(3));
f.wait_until(tp);
return 0;
}



