多线程mutex_qq
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<mutex>,它会自己解锁。在某个lock_guard对象的声明周期内,它所管理的锁对象会一直保持上锁状态;而lock_guard的生命周期结束之后,它所管理的锁对象会被解锁。
- void A()
- {
- for (int i=0;i<100000;++i)
- {
- lock_guard<mutex> 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<mutex> lockmu(mu);
- sum++;
- lock_guard<mutex> lockmu2(mu2);
- sum++;
- }
- cout << "a is :" << sum << endl;
- }
-
- void B()
- {
- for (int i = 0; i < 100000; ++i)
- {
- lock_guard<mutex> lockmu2(mu2);
- sum++;
- lock_guard<mutex> 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<mutex> lockmu(mu,adopt_lock);
- sum++;
- lock_guard<mutex> lockmu2(mu2, adopt_lock);
- sum++;
- }
- cout << "a is :" << sum << endl;
- }
-
- void B()
- {
- for (int i = 0; i < 100000; ++i)
- {
- lock(mu, mu2);
- lock_guard<mutex> lockmu2(mu2, adopt_lock);
- sum++;
- lock_guard<mutex> 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;
- vector<int> sum;
- void A()
- {
- for (int i = 0; i < 10; ++i)
- {
- unique_lock<mutex> locker(mu);
- cv.notify_one();
- sum.emplace_back(i);
- cout << "sum is:" << i << endl;
- }
- }
-
- void B()
- {
- int data = 0;
- while (data!=9)
- {
- unique_lock<mutex> 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<int> &p)
- {
- cout << "1:" << endl;
- p.set_value(10);
- cout << "3:" << endl;
- int a = 20;
- a = a * 10;
- cout << "data is:" <<a << endl;
- }
-
- void B(future<int>& f)
- {
- cout << "2:" << endl;
- int data =f.get();
- cout << "data is:" << data <<endl;
- }
-
- int main()
- {
- promise<int> pro;
- future<int> 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<int(int, int&)> t(A);
- future<int> f = t.get_future();
- int num = 10;
- thread a(move(t),10, ref(num));
- a.join();
- int b= f.get();
- cout << "b is :" <<b<< endl;
- cout << "num is :" << num << endl;
- return 0;
- }
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<mutex> 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<int> p;
- future<int> f = p.get_future();
- f.wait_for(chrono::microseconds(3));
- f.wait_until(tp);
- return 0;
- }