久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

在調用condition_variable.notify_one() 之前是否必須獲取

Do I have to acquire lock before calling condition_variable.notify_one()?(在調用condition_variable.notify_one() 之前是否必須獲取鎖?)
本文介紹了在調用condition_variable.notify_one() 之前是否必須獲取鎖?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我對 std::condition_variable 的使用有點困惑.我知道我必須在調用 condition_variable.wait() 之前在 mutex 上創建一個 unique_lock.我找不到的是我是否應該在調用 notify_one()notify_all() 之前獲取唯一鎖.

I am a bit confused about the use of std::condition_variable. I understand I have to create a unique_lock on a mutex before calling condition_variable.wait(). What I cannot find is whether I should also acquire a unique lock before calling notify_one() or notify_all().

cppreference.com 上的示例相互矛盾.例如,notify_one 頁面給出了這個例子:

Examples on cppreference.com are conflicting. For example, the notify_one page gives this example:

#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>

std::condition_variable cv;
std::mutex cv_m;
int i = 0;
bool done = false;

void waits()
{
    std::unique_lock<std::mutex> lk(cv_m);
    std::cout << "Waiting... 
";
    cv.wait(lk, []{return i == 1;});
    std::cout << "...finished waiting. i == 1
";
    done = true;
}

void signals()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Notifying...
";
    cv.notify_one();

    std::unique_lock<std::mutex> lk(cv_m);
    i = 1;
    while (!done) {
        lk.unlock();
        std::this_thread::sleep_for(std::chrono::seconds(1));
        lk.lock();
        std::cerr << "Notifying again...
";
        cv.notify_one();
    }
}

int main()
{
    std::thread t1(waits), t2(signals);
    t1.join(); t2.join();
}

這里的鎖不是為第一個 notify_one() 獲取的,而是為第二個 notify_one() 獲取的.查看帶有示例的其他頁面,我看到了不同的東西,主要是沒有獲取鎖.

Here the lock is not acquired for the first notify_one(), but is acquired for the second notify_one(). Looking though other pages with examples I see different things, mostly not acquiring the lock.

  • 在調用notify_one()之前我可以選擇自己鎖定互斥鎖嗎,為什么我會選擇鎖定它?
  • 在給出的示例中,為什么第一個 notify_one() 沒有鎖定,但后續調用有鎖定.這個例子是錯誤的還是有一些道理?
  • Can I choose myself to lock the mutex before calling notify_one(), and why would I choose to lock it?
  • In the example given, why is there no lock for the first notify_one(), but there is for subsequent calls. Is this example wrong or is there some rationale?

推薦答案

在調用 condition_variable::notify_one() 時不需要持有鎖,但從某種意義上說這并沒有錯它仍然是明確定義的行為,而不是錯誤.

You do not need to be holding a lock when calling condition_variable::notify_one(), but it's not wrong in the sense that it's still well defined behavior and not an error.

然而,這可能是一種悲觀化",因為任何等待線程被設為可運行(如果有)將立即嘗試獲取通知線程持有的鎖.我認為在調用 notify_one()notify_all() 時避免持有與條件變量關聯的鎖是一個很好的經驗法則.請參閱 Pthread Mutex:pthread_mutex_unlock() 消耗大量時間 例如,在調用與 notify_one() 等效的 pthread 之前釋放鎖顯著提高了性能.

However, it might be a "pessimization" since whatever waiting thread is made runnable (if any) will immediately try to acquire the lock that the notifying thread holds. I think it's a good rule of thumb to avoid holding the lock associated with a condition variable while calling notify_one() or notify_all(). See Pthread Mutex: pthread_mutex_unlock() consumes lots of time for an example where releasing a lock before calling the pthread equivalent of notify_one() improved performance measurably.

請記住,while 循環中的 lock() 調用在某些時候是必要的,因為需要在 while (!done) 循環條件檢查.但是對于 notify_one() 的調用不需要保持它.

Keep in mind that the lock() call in the while loop is necessary at some point, because the lock needs to be held during the while (!done) loop condition check. But it doesn't need to be held for the call to notify_one().

2016-02-27:大型更新解決了評論中關于是否存在競爭條件是鎖對 notify_one() 沒有幫助的一些問題稱呼.我知道這個更新晚了,因為這個問題是在大約兩年前提出的,但我想解決@Cookie 的問題,如果生產者(在這個例子中為 signals())調用notify_one() 就在消費者(本例中為waits())能夠調用wait()之前.

2016-02-27: Large update to address some questions in the comments about whether there's a race condition is the lock isn't help for the notify_one() call. I know this update is late because the question was asked almost two years ago, but I'd like to address @Cookie's question about a possible race condition if the producer (signals() in this example) calls notify_one() just before the consumer (waits() in this example) is able to call wait().

關鍵是 i 發生了什么 - 這是實際指示消費者是否有工作"要做的對象.condition_variable 只是一種讓消費者有效等待 i 更改的機制.

The key is what happens to i - that's the object that actually indicates whether or not the consumer has "work" to do. The condition_variable is just a mechanism to let the consumer efficiently wait for a change to i.

生產者在更新i時需要持有鎖,消費者在檢查i和調用condition_variable::wait()時必須持有鎖(如果它需要等待).在這種情況下,關鍵是當消費者執行此檢查和等待時,它必須是持有鎖的同一實例(通常稱為臨界區).由于臨界區在生產者更新 i 和消費者檢查并等待 i 時被保留,所以 i 沒有機會在消費者檢查 i 和調用 condition_variable::wait() 之間切換.這是正確使用條件變量的關鍵.

The producer needs to hold the lock when updating i, and the consumer must hold the lock while checking i and calling condition_variable::wait() (if it needs to wait at all). In this case, the key is that it must be the same instance of holding the lock (often called a critical section) when the consumer does this check-and-wait. Since the critical section is held when the producer updates i and when the consumer checks-and-waits on i, there is no opportunity for i to change between when the consumer checks i and when it calls condition_variable::wait(). This is the crux for a proper use of condition variables.

C++ 標準規定,當使用謂詞調用時,condition_variable::wait() 的行為如下(如本例所示):

The C++ standard says that condition_variable::wait() behaves like the following when called with a predicate (as in this case):

while (!pred())
    wait(lock);

消費者檢查i時可能出現兩種情況:

There are two situations that can occur when the consumer checks i:

  • 如果i為0,則消費者調用cv.wait(),則iwait(lock) 部分實現被調用 - 正確使用鎖確保了這一點.在這種情況下,生產者沒有機會在其 while 循環中調用 condition_variable::notify_one() 直到消費者調用 cv.wait(lk,[]{return i == 1;}) (并且 wait() 調用已經完成了正確捕捉"通知所需的一切 - wait() 在它完成之前不會釋放鎖).所以在這種情況下,消費者不會錯過通知.

  • if i is 0 then the consumer calls cv.wait(), then i will still be 0 when the wait(lock) part of the implementation is called - the proper use of the locks ensures that. In this case the producer has no opportunity to call the condition_variable::notify_one() in its while loop until after the consumer has called cv.wait(lk, []{return i == 1;}) (and the wait() call has done everything it needs to do to properly 'catch' a notify - wait() won't release the lock until it has done that). So in this case, the consumer cannot miss the notification.

如果當消費者調用cv.wait()i已經為1,則wait(lock)部分永遠不會調用實現,因為 while (!pred()) 測試將導致內部循環終止.在這種情況下,何時調用 notify_one() 無關緊要 - 消費者不會阻塞.

if i is already 1 when the consumer calls cv.wait(), the wait(lock) part of the implementation will never be called because the while (!pred()) test will cause the internal loop to terminate. In this situation it doesn't matter when the call to notify_one() occurs - the consumer will not block.

此處的示例確實具有額外的復雜性,即使用 done 變量向生產者線程發信號通知消費者已識別 i == 1,但我不要認為這根本不會改變分析,因為對 done 的所有訪問(用于讀取和修改)都是在涉及 icondition_variable.

The example here does have the additional complexity of using the done variable to signal back to the producer thread that the consumer has recognized that i == 1, but I don't think this changes the analysis at all because all of the access to done (for both reading and modifying) are done while in the same critical sections that involve i and the condition_variable.

如果你看看@eh9 指出的問題,同步使用 std::atomic 和 std::condition_variable 不可靠,您看到競爭條件.但是,該問題中發布的代碼違反了使用條件變量的基本規則之一:在執行檢查和等待時,它不包含單個臨界區.

If you look at the question that @eh9 pointed to, Sync is unreliable using std::atomic and std::condition_variable, you will see a race condition. However, the code posted in that question violates one of the fundamental rules of using a condition variable: It does not hold a single critical section when performing a check-and-wait.

在該示例中,代碼如下所示:

In that example, the code looks like:

if (--f->counter == 0)      // (1)
    // we have zeroed this fence's counter, wake up everyone that waits
    f->resume.notify_all(); // (2)
else
{
    unique_lock<mutex> lock(f->resume_mutex);
    f->resume.wait(lock);   // (3)
}

您會注意到#3 處的wait() 是在保持f->resume_mutex 的同時執行的.但是在第 1 步檢查 wait() 是否有必要沒有在持有該鎖的情況下完成(更不用說連續檢查和 -等待),這是正確使用條件變量的要求).我相信對該代碼片段有問題的人認為,由于 f->counter 是一個 std::atomic 類型,這將滿足要求.但是,std::atomic 提供的原子性不會擴展到對 f->resume.wait(lock) 的后續調用.在此示例中,在檢查 f->counter 時(步驟 1)和調用 wait() 時(步驟 3)之間存在競爭.

You will notice that the wait() at #3 is performed while holding f->resume_mutex. But the check for whether or not the wait() is necessary at step #1 is not done while holding that lock at all (much less continuously for the check-and-wait), which is a requirement for proper use of condition variables). I believe that the person who has the problem with that code snippet thought that since f->counter was a std::atomic type this would fulfill the requirement. However, the atomicity provided by std::atomic doesn't extend to the subsequent call to f->resume.wait(lock). In this example, there is a race between when f->counter is checked (step #1) and when the wait() is called (step #3).

這個問題的例子中不存在那個種族.

That race does not exist in this question's example.

這篇關于在調用condition_variable.notify_one() 之前是否必須獲取鎖?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

What is the fastest way to transpose a matrix in C++?(在 C++ 中轉置矩陣的最快方法是什么?)
Sorting zipped (locked) containers in C++ using boost or the STL(使用 boost 或 STL 在 C++ 中對壓縮(鎖定)容器進行排序)
Rotating a point about another point (2D)(圍繞另一個點旋轉一個點 (2D))
Image Processing: Algorithm Improvement for #39;Coca-Cola Can#39; Recognition(圖像處理:Coca-Cola Can 識別的算法改進)
How do I construct an ISO 8601 datetime in C++?(如何在 C++ 中構建 ISO 8601 日期時間?)
Sort list using STL sort function(使用 STL 排序功能對列表進行排序)
主站蜘蛛池模板: 日韩中文字幕高清 | a级毛片毛片免费观看久潮喷 | 九九九久久国产免费 | 九九热在线精品视频 | 蜜桃传媒av | 日本天天操 | 久久亚洲天堂 | 国产一区二区a | 草草视频在线观看 | www.久久99| 伊人网综合在线观看 | 亚洲a视| 色免费视频| 一本大道久久a久久精二百 国产成人免费在线 | 99精品观看 | 在线观看视频一区 | 亚洲精品久久久久中文字幕欢迎你 | www久久久 | 黄瓜av| 久久国产婷婷国产香蕉 | 中文字幕不卡一区 | 久草网站 | 国产精品亚洲综合 | 97综合在线 | 天天操操 | 可以看黄的视频 | 国产麻豆一区二区三区 | 日本a v在线播放 | 综合网视频 | 日韩欧美在线视频 | 在线一区 | 涩涩片影院 | 成人福利网站 | 亚洲国产成人精品久久 | 成人精品免费视频 | av一区二区三区 | 国产精品电影网 | 黄色三级毛片 | 黄网免费 | www.色午夜.com | 久久亚洲春色中文字幕久久久 |