189 8069 5689

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

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

创新互联建站从2013年成立,是专业互联网技术服务公司,拥有项目成都网站设计、做网站网站策划,项目实施与项目整合能力。我们以让每一个梦想脱颖而出为使命,1280元沁水做网站,已为上家服务,为沁水各地企业和个人服务,联系电话:18980820575

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

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

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

例子:

#include 
 #include 
 #include 
 #include 
  
 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 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 
 #include 
 #include 
 #include 
  
 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 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 
 #include 
 #include 
 #include 
  
 class A
 {
 public:
     void WriteFunction()
     {
         for (int i = 0; i < 1000; ++i)
         {
             std::lock_guard 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 my_lock_guard(my_mutex_1);
                 if (!my_deque.empty())
                 {
                     std::cout << "读出队列的第一个元素: " << my_deque.front() << std::endl;
                     my_deque.pop_front();
                 }
  
             }
             
         }
     }
 private:
     std::deque 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 my_lock_guard(my_mutex_1);这句代码代替了lock()和unlock().

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

这样做的原理:std::lock_guard 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和锁的应用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!


分享文章:c++互斥量mutex和锁的应用
本文来源:http://cdxtjz.com/article/ihhhdd.html

其他资讯