• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

【C++多线程】共享数据保护

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

  保护共享数据的最基本的方式,是使用C++标准库提供的互斥量(头文件<mutex>)。当访问共享数据前,使用互斥量将相关数据锁住,再当访问结束后,再将数据解锁。线程库需要保证,当一个线程使用特定互斥量锁住共享数据时,其他的线程想要访问锁住的数据,都必须等到之前那个线程对数据进行解锁后,才能进行访问。这就保证了所有线程能看到共享数据,而不破坏不变量。

  C++中通过实例化 std::mutex 创建互斥量,通过调用成员函数lock()进行上锁,unlock()进行解锁。

 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 #include <list>
 5 
 6 using namespace std;
 7 
 8 class A {
 9 public:
10     void input()
11     {
12         for (int i = 0; i < 1000; i++)
13         {
14             my_mutex.lock();
15             cout << "加入数据:" << i << endl;
16             ilst.push_back(i);
17             my_mutex.unlock();
18         }
19 
20     }
21 
22     void output()
23     {
24         for (int i = 0; i < 1000; i++)
25         {
26             my_mutex.lock();
27             if (!ilst.empty())
28             {
29                 cout << "读读读读出数据:" << ilst.front() << endl;
30                 ilst.pop_front();
31                 my_mutex.unlock();
32             }
33             else
34                 my_mutex.unlock();
35         }
36     }
37 
38 private:
39     list<int> ilst;
40     mutex my_mutex;
41 };
42 
43 int  main()
44 {
45     A a;
46     thread t1(&A::input, &a); //注意此处需要传入的是对象地址,否则数据没办法共享
47     thread t2(&A::output, &a);
48     t1.join();
49     t2.join();
50     return 0;
51 }

 

  C++标准库还为互斥量提供了一个RAII语法的模板类 std::lack_guard<T> ,其会在构造的时候提供已锁的互斥量,并在析构的时候进行解锁,从而保证了一个已锁的互斥量总是会被正确的解锁。

 1 #include <iostream>
 2 #include <thread>
 3 #include <mutex>
 4 #include <list>
 5 
 6 using namespace std;
 7 
 8 class A {
 9 public:
10     void input()
11     {
12         for (int i = 0; i < 1000; i++)
13         {
14             lock_guard<mutex> guard(my_mutex);
15             /*my_mutex.lock();*/
16             cout << "加入数据:" << i << endl;
17             ilst.push_back(i);
18            /* my_mutex.unlock();*/
19         }
20 
21     }
22 
23     void output()
24     {
25         for (int i = 0; i < 1000; i++)
26         {
27             lock_guard<mutex> guard(my_mutex);
28             /*my_mutex.lock();*/
29             if (!ilst.empty())
30             {
31                 cout << "读读读读出数据:" << ilst.front() << endl;
32                 ilst.pop_front();
33                 /*my_mutex.unlock();*/
34             }
35             /*else
36                 my_mutex.unlock();*/
37         }
38     }
39 
40 private:
41     list<int> ilst;
42     mutex my_mutex;
43 };
44 
45 int  main()
46 {
47     A a;
48     thread t1(&A::input, &a); //注意此处需要传入的是对象地址,否则数据没办法共享
49     thread t2(&A::output, &a);
50     t1.join();
51     t2.join();
52     return 0;
53 }

 

  但互斥量自身也有问题。

  当其中一个成员函数返回的是保护数据的指针或引用时,会破坏对数据的保护。具有访问能力的指针或引用可以访问(并可能修改)被保护的数据,而不会被互斥锁限制。所以切勿将受保护数据的指针或引用传递到互斥锁作用域之外,无论是函数返回值,还是存储在外部可见内存,亦或是以参数的形式传递到用户提供的函数中去。

  另外还会造成死锁,或是对数据保护的太多(或太少)的问题

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
使用OpenCV(C++/Python)进行人脸交换发布时间:2022-07-13
下一篇:
C#HttpWebRequest请求远程地址获取返回消息发布时间:2022-07-13
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap