以及为什么我们需要同时使用

以及为什么我们需要同时使用

本文介绍了请说明条件变量在c ++线程中的用法,以及为什么我们需要同时使用`unique_lock`和`mutex`的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我指的是这段特定的代码:

I am refering to this particular piece of code:

这段代码基本上有三个线程1.与服务器进行一些握手2.从XML文件加载数据.3.对从XML加载的数据进行处理.我们可以看到任务1不依赖于任何其他任务,但是任务3依赖于任务2.因此,这意味着任务1和任务2可以由不同的线程并行运行以提高应用程序的性能.因此,应用程序被构建为多线程的.

this code basically has three threads1. Perform some handshaking with server2. Load Data from XML files.3. Do processing on data loaded from XML.As we can see that Task 1 is not dependent on any other Tasks but Task 3 is dependent on Task 2. So, it means Task 1 and Task 2 can be run in parallel by different Threads to improve the performance of application. Thus, application is built to be multithreaded.

#include <iostream>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>
using namespace std::placeholders;

class Application
{
  std::mutex m_mutex;
  std::condition_variable m_condVar;
  bool m_bDataLoaded;
public:
  Application()
  {
    m_bDataLoaded = false;
  }
  void loadData()
  {
   // Make This Thread sleep for 1 Second
   std::this_thread::sleep_for(std::chrono::milliseconds(1000));
   std::cout<<"Loading Data from XML"<<std::endl;
   // Lock The Data structure
   std::lock_guard<std::mutex> guard(m_mutex);
   // Set the flag to true, means data is loaded
   m_bDataLoaded = true;
   // Notify the condition variable
   m_condVar.notify_one();
  }
  bool isDataLoaded()
  {
    return m_bDataLoaded;
  }
  void mainTask()
  {
    std::cout<<"Do Some Handshaking"<<std::endl;
    // Acquire the lock
    std::unique_lock<std::mutex> mlock(m_mutex);
    // Start waiting for the Condition Variable to get signaled
    // Wait() will internally release the lock and make the thread to block
    // As soon as condition variable get signaled, resume the thread and
    // again acquire the lock. Then check if condition is met or not
    // If condition is met then continue else again go in wait.
    m_condVar.wait(mlock, std::bind(&Application::isDataLoaded, this));
    std::cout<<"Do Processing On loaded Data"<<std::endl;
  }
};
int main()
{
   Application app;
   std::thread thread_1(&Application::mainTask, &app);
   std::thread thread_2(&Application::loadData, &app);
   thread_2.join();
   thread_1.join();
   return 0;
}

此代码来自 http://thispointer.com/c11-multithreading-part-7-条件变量说明/

谢谢

推荐答案

条件变量允许原子自动释放所持有的互斥量并使线程进入睡眠状态.然后,在收到信号后,以原子方式重新获取互斥锁并唤醒.例如,您在生产者/消费者问题中遇到了这种情况.如果您在保持互斥锁的状态下进入睡眠状态,则会 进入死锁状态,但是如果在睡眠前释放互斥锁,则可能也会死锁(由于缺少唤醒信号).

Condition variables allow one to atomically release a held mutex and put the thread to sleep. Then, after being signaled, atomically re-acquire the mutex and wake up. You run into this, for example, in the producer/consumer problem. You will deadlock if you go to sleep while holding the mutex, but you could also deadlock if you release it before sleeping (by missing the signal to wake up).

在没有示例的情况下,不能在几段中对此进行解释,并且使用条件变量存在一些众所周知的陷阱和警告.查阅Andrew D. Birrell撰写的线程编程简介".

It's not something that can be explained in a few paragraphs without examples, and there are several well-known pitfalls and caveats to using condition variables. Check out "An Introduction to Programming with Threads" by Andrew D. Birrell.

无论使用哪种语言,条件变量始终使用互斥量.调用wait时必须保留互斥量.从等待返回后,您应始终验证所需条件是否仍然为真.这就是为什么您总是看到条件等待包裹在while循环中的原因. C ++ 11还为您提供谓词重载,这是while循环的语法糖.

Regardless of the language, condition variables always take a mutex. The mutex must be held when wait is called. You should always verify that the desired condition is still true after returning from wait. That's why you always see conditional waits wrapped in a while loop. C++11 also gives you the predicate overload, which is syntactic sugar for the while loop.

互斥锁保护共享状态.这种情况让您一直封锁直到发信号为止.

The mutex protects the shared state. The condition lets you block until signaled.

unique_lock是RAII(资源获取为初始化)包装,用于锁定和解锁给定的互斥锁.从概念上讲,它与C#中的lock语句相同.通过将互斥锁的获取和释放绑定到unique_lock实例的生存期,可以简化异常处理.我不知道condition_variable是否有理由强迫您使用它,除了事实证明这是一个好习惯之外. unique_locklock_guard之间的唯一区别是unique_lock可以被解锁...这就是为什么必须使用它而不是lock_guardcondition_variable的原因.

unique_lock is an RAII (Resource Acquisition Is Initialization) wrapper for locking and unlocking the given mutex. It's conceptually identical to the lock statement in C#. It simplifies exception handling by tying the mutex acquisition and release to the lifetime of the unique_lock instance. I don't know if there's a reason why condition_variable forces you to use it other than the fact that it's good practice. The only difference between unique_lock and lock_guard is that unique_lock can be unlocked... which is why you have to use it instead of lock_guard with condition_variable.

这篇关于请说明条件变量在c ++线程中的用法,以及为什么我们需要同时使用`unique_lock`和`mutex`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 11:22