1. 程式人生 > >多執行緒-條件變數

多執行緒-條件變數

條件變數是一個能夠阻止呼叫執行緒直到通知恢復的物件。

它使用unique_lock(通過互斥鎖)在呼叫其中一個等待函式時鎖定執行緒。執行緒保持阻塞狀態,直到被另一個呼叫相同condition_variable物件上的通知函式的執行緒喚醒。

condition_variable型別的物件總是使用unique_lock <mutex>來等待:對於適用於任何型別的可鎖定型別的替代,請參閱condition_variable_any

condition_variable()建構函式

default (1)
condition_variable();
copy [deleted] (2)
condition_variable (const condition_variable&) = delete;

 作用:構造一個條件變數物件。條件變數沒有複製和賦值建構函式。

wait()成員函式

unconditional (1)
void wait (unique_lock<mutex>& lck);
predicate (2)
template <class Predicate>
  void wait (unique_lock<mutex>& lck, Predicate pred);

當前執行緒(應鎖定lck的互斥鎖)的執行被阻止,直到通知為止。在阻塞執行緒的那一刻,該函式自動呼叫lck.unlock(),允許其他鎖定的執行緒繼續。

一旦被notified()(顯式地,由其他一些執行緒),該函式解除阻塞並呼叫lck.lock(),使lck處於與呼叫函式時相同的狀態。然後函式返回(注意,最後一個互斥鎖定可能會在返回之前再次阻塞執行緒)

通常,另一個執行緒呼叫notify_one()或者成員函式notify_all(),喚醒被阻塞的執行緒,然後執行緒獲得互斥鎖。但某些實現可能會產生虛假的喚醒呼叫,而不會呼叫任何這些函式。因此,該功能的使用者應確保滿足其恢復條件。

在(2)中,如果如果pred返回false,該函式僅阻止,並且只有當pred為true時才發出通知,解除阻塞。

引數說明:lck  -- 一個unique_lock物件,並且它的mutex object 被當前執行緒 locked;

                  pred --一個不帶引數的可呼叫物件或函式,返回一個可以作為bool計算的值。 重複呼叫它直到它的計算結果為true。

// condition_variable::wait (with predicate)
#include <iostream>           // std::cout
#include <thread>             // std::thread, std::this_thread::yield
#include <mutex>              // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable

std::mutex mtx;
std::condition_variable cv;

int cargo = 0;
bool shipment_available() {return cargo!=0;}

void consume (int n) {
  for (int i=0; i<n; ++i) {
    std::unique_lock<std::mutex> lck(mtx);
    cv.wait(lck,shipment_available);
    // consume:
    std::cout << cargo << '\n';
    cargo=0;
  }
}

int main ()
{
  std::thread consumer_thread (consume,10);

  // produce 10 items when needed:
  for (int i=0; i<10; ++i) {
    while (shipment_available()) std::this_thread::yield();
    std::unique_lock<std::mutex> lck(mtx);
    cargo = i+1;
    cv.notify_one();
  }

  consumer_thread.join();

  return 0;
}

Output:

1
2
3
4
5
6
7
8
9
10