温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

c++互斥量mutex和锁的应用

发布时间:2021-07-13 10:44:05 来源:亿速云 阅读:191 作者:chen 栏目:互联网科技

本篇内容介绍了“c++互斥量mutex和锁的应用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

多线程中,多个线程对共享的数据进行访问,应该是最常见的应用。

如果多个线程都只是对共享数据进行读操作,还不会有问题,但是如果有的线程读数据,有的线程写数据,这时候就会出现问题。比如A线程写数据,但是写的这个过程进行到一半,B线程就去读,这个时候程序就会崩溃。这个时候就需要互斥量的出场啦!

mutex:
mutex互斥量是一个类,这个类有有一个lock()方法,和一个unlock()方法。如果第一次运行了lock()这个方法,而没有运行unlock()这个方法,第二次再运行lock()这个方法时,程序就会卡停在这里,只有当运行了unlock()这个方法运行后,第二个lock()方法才会运行通过。就是运用这种“锁”的机制就可以保证两段代码独立运行。

例子:

#include <iostream>
 #include <thread>
 #include <mutex>
 #include <deque>
  
 class A
 {
 public:
     void WriteFunction()
     {
         for (int i = 0; i < 1000; ++i)
         {
             
             std::cout << "向队列中添加一个元素" << std::endl;
             my_deque.push_back(i);
             
         }
     }
     void ReadFunction()
     {
         for (int i = 0; i < 1000; ++i)
         {
             
             if(!my_deque.empty())
             {
                 std::cout << "读出队列的第一个元素: " << my_deque.front() << std::endl;
                 my_deque.pop_front();
             }
             
         }
     }
 private:
     std::deque<int> my_deque;
     
  
 };
 int main()
 {
     A a;
     std::thread my_thread_1(&A::WriteFunction, std::ref(a));
  
     std::thread my_thread_2(&A::ReadFunction, std::ref(a));
  
     my_thread_1.join();
     my_thread_2.join();
     std::cout << "Hello World!\n";
 }


 
上面这段代码运行时,会出现错误的。原因就是上面提到的:读写可能会同时操作,出现错误。

修改的代码:

#include <iostream>
 #include <thread>
 #include <mutex>
 #include <deque>
  
 class A
 {
 public:
     void WriteFunction()
     {
         for (int i = 0; i < 1000; ++i)
         {
             my_mutex_1.lock();
             std::cout << "向队列中添加一个元素" << std::endl;
             my_deque.push_back(i);
             my_mutex_1.unlock();
         }
     }
     void ReadFunction()
     {
         for (int i = 0; i < 1000; ++i)
         {
             my_mutex_1.lock();
             if(!my_deque.empty())
             {
                 std::cout << "读出队列的第一个元素: " << my_deque.front() << std::endl;
                 my_deque.pop_front();
             }
             my_mutex_1.unlock();
         }
     }
 private:
     std::deque<int> my_deque;
     std::mutex my_mutex_1;
  
 };
 int main()
 {
     A a;
     std::thread my_thread_1(&A::WriteFunction, std::ref(a));
  
     std::thread my_thread_2(&A::ReadFunction, std::ref(a));
  
     my_thread_1.join();
     my_thread_2.join();
     std::cout << "Hello World!\n";
 }


 
上面这段代码,我们运用了互斥量和锁的方法,解决了上面的问题。

注意事项:
lock()和unlock()必须同时成对出现,不可以多写,也不可以少写,要不认会出现不知名的错误。

std::lock_guard() 
这是一个类模板,具体的用法可以看下面的代码。

这个类模板的作用就是替代lock()和unlock()。lock()和unlock()必须同时出现,而std::lock_guard() 只需要出现一个就行。

先来看代码:

#include <iostream>
 #include <thread>
 #include <mutex>
 #include <deque>
  
 class A
 {
 public:
     void WriteFunction()
     {
         for (int i = 0; i < 1000; ++i)
         {
             std::lock_guard<std::mutex> my_lock_guard(my_mutex_1);
             std::cout << "向队列中添加一个元素" << std::endl;
             my_deque.push_back(i);
         }
     }
     void ReadFunction()
     {
         for (int i = 0; i < 1000; ++i)
         {
             {//其实这个大括号不用写,因为这里恰巧有for循环的大括号
                 std::lock_guard<std::mutex> my_lock_guard(my_mutex_1);
                 if (!my_deque.empty())
                 {
                     std::cout << "读出队列的第一个元素: " << my_deque.front() << std::endl;
                     my_deque.pop_front();
                 }
  
             }
             
         }
     }
 private:
     std::deque<int> my_deque;
     std::mutex my_mutex_1;
  
 };
 int main()
 {
     A a;
     std::thread my_thread_1(&A::WriteFunction, std::ref(a));
  
     std::thread my_thread_2(&A::ReadFunction, std::ref(a));
  
     my_thread_1.join();
     my_thread_2.join();
     std::cout << "Hello World!\n";
 }

上面的代码我们用std::lock_guard<std::mutex> my_lock_guard(my_mutex_1);这句代码代替了lock()和unlock().

我一般这样使用:将需要保护的代码段用一个大括号括起来,然后在大括号括起来的代码的第一句定义std::lock_guard()。

这样做的原理:std::lock_guard<std::mutex> my_lock_guard(my_mutex_1);我们定义的std::lock_guard()对象只在这个大括号的作用域内有效。当进入这个作用域时,我们会构造std::lock_guard()对象,在std::lock_guard()的构造函数中其实是执行了lock()这个方法,当退出这个作用域的时候,std::lock_guard()对象将会被析构,而在std::lock_guard()的析构函数中实际是调用了unlock()。这样的操作十分巧妙。

“c++互斥量mutex和锁的应用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

c++
AI