Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 条件变量真的需要另一个变量吗? 我会给出C++的例子,但是我相信我的问题是语言不可知的。如果我错了,请纠正我_Multithreading_Language Agnostic_Condition Variable - Fatal编程技术网

Multithreading 条件变量真的需要另一个变量吗? 我会给出C++的例子,但是我相信我的问题是语言不可知的。如果我错了,请纠正我

Multithreading 条件变量真的需要另一个变量吗? 我会给出C++的例子,但是我相信我的问题是语言不可知的。如果我错了,请纠正我,multithreading,language-agnostic,condition-variable,Multithreading,Language Agnostic,Condition Variable,只是想让你真正了解我-我在这里试图学习的是工具的功能,而不是其他。不是它通常用来做什么,不是惯例所说的,只是钝器工具所做的。在本例中-条件变量的作用 到目前为止,在我看来,这是一种简单的机制,允许线程等待(阻塞),直到其他线程发出信号(解除阻塞)。除此之外,无需处理关键部分访问或数据访问(当然,它们可以用于此,但这只是程序员的选择问题)。此外,信号通常仅在发生重要事件(如加载数据)时才发出,但理论上可以随时调用。到目前为止正确吗 现在,我看到的每个示例都使用一个条件变量对象(例如std::con

只是想让你真正了解我-我在这里试图学习的是工具的功能,而不是其他。不是它通常用来做什么,不是惯例所说的,只是钝器工具所做的。在本例中-条件变量的作用

到目前为止,在我看来,这是一种简单的机制,允许线程等待(阻塞),直到其他线程发出信号(解除阻塞)。除此之外,无需处理关键部分访问或数据访问(当然,它们可以用于此,但这只是程序员的选择问题)。此外,信号通常仅在发生重要事件(如加载数据)时才发出,但理论上可以随时调用。到目前为止正确吗

现在,我看到的每个示例都使用一个条件变量对象(例如
std::condition_variable
),但也使用一些附加变量来标记是否发生了什么事情(例如
bool datawasload
)。请从以下方面查看此示例:

  • 现在我知道了虚假唤醒,它们本身就需要使用额外的变量。我的问题是——他们是否仅仅是原因?如果它们没有出现,我们可以只使用条件变量而不使用任何附加变量吗(顺便说一句,“条件变量”这个名称不是用词不当吗)
  • 另一件事是-使用附加变量不是条件变量也需要互斥的唯一原因吗?如果没有,还有什么原因
  • 如果需要额外的变量(出于虚假唤醒或其他原因),为什么API不需要它们(在第二段代码中,我不必使用它们来编译代码)?(我不知道在其他语言中是否相同,所以这个问题可能是C++特有的。)

  • 这不全是虚假的觉醒

    当您调用
    m_condvar.wait
    时,您如何知道等待的条件尚未发生

    可能已经在另一个线程中调用了“loadData”。当它调用
    notify_one()
    时,由于没有线程等待,所以什么也没有发生

    现在,如果您调用
    condvar.wait
    ,您将永远等待,因为没有任何信号会通知您

    原始版本没有此问题,因为:

  • 如果
    m_bDataLoaded
    为false,则它知道数据未加载,并且在
    m_bDataLoaded
    设置为true后,调用者将发出条件信号
  • 锁被持有,我们知道
    m_bDataLoaded
    不能在另一个线程中修改,直到它被释放
  • condvar.wait
    将在释放锁之前将当前线程放入等待队列中,因此我们知道
    m_bDataLoaded
    将在开始等待后设置为true,因此在开始等待后也将调用
    notify_one
  • 要回答您的其他问题:

    • 是的,与其他变量的协调是条件变量绑定到互斥体的原因
    • 比如说,API不需要布尔变量,因为这并不总是您所等待的条件
    这类事情很常见,例如:

    Task *getTask() {
        //anyone who uses m_taskQueue or m_shutDown must lock this mutex
        unique_lock<mutex> lock(m_mutex);
    
        while (m_taskQueue.isEmpty()) {
            if (m_shutdown) {
                return null;
            }
            // this is signalled after a task is enqueued
            // or m_shutdown is asserted
            m_condvar.wait(lock);
        }
        return taskQueue.pop_front();
    }
    
    Task*getTask(){
    //使用m_taskQueue或m_shutDown的任何人都必须锁定此互斥锁
    唯一的_锁(m_互斥锁);
    while(m_taskQueue.isEmpty()){
    如果(m_关闭){
    返回null;
    }
    //这是在任务排队后发出的信号
    //或m_shutdown被断言
    m_condvar.等待(锁定);
    }
    返回taskQueue.pop_front();
    }
    

    在这里,我们需要同样的关键保证,即线程在释放锁之前开始等待,但我们等待的条件更复杂,涉及一个变量和单独的数据结构,并且有多种方法退出等待

    好吧,虽然我承认在大多数情况下可能需要额外的变量,但我认为仍然有一些场景不需要它们(即使这些场景对任何实际情况都没有用处)。就像在我提供的第二个示例中,我们知道一切都将以正确的顺序运行(除非
    mainTask
    以某种方式延迟超过1秒,并在
    notify\u one
    之后开始等待,我不知道这是否可能)。我的假设正确吗?当然,但你怎么知道主任务延迟不超过一秒钟?依赖那样的东西是危险的。你能提供2个问题的答案吗。三,。在我最初的帖子中?当然,没有问题API不能要求任何类型的变量(使用模板或其他什么)?
    #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;
    public:
        Application()
        {
        }
        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);
            // Notify the condition variable
            m_condVar.notify_one();
        }
        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::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;
    }
    
    Task *getTask() {
        //anyone who uses m_taskQueue or m_shutDown must lock this mutex
        unique_lock<mutex> lock(m_mutex);
    
        while (m_taskQueue.isEmpty()) {
            if (m_shutdown) {
                return null;
            }
            // this is signalled after a task is enqueued
            // or m_shutdown is asserted
            m_condvar.wait(lock);
        }
        return taskQueue.pop_front();
    }