程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++0x概覽:多線程(2)

C++0x概覽:多線程(2)

編輯:關於C++

數據保護

同許多線程API一樣,C++0x用互斥來保護共享數據。有四種互斥類型:

Non-recursive (std::mutex)

Recursive (std::recursive_mutex)

允許鎖超時的non-recursive (std::timed_mutex)

允許鎖超時的recursive (std::recursive_timed_mutex)

如果你試圖在一個線程上鎖(lock)一個non-recursive mutex兩次而當中沒有unlock它的話,會產生未知結果。遞歸recur6sive mutex只是增加鎖的計數,因此必須確保你unlock和lock的次數相同,其他線程才可能鎖這個mutex。

通常我們用模板類std::unique_lock<>和std::lock_guard<>來lock和unlock一個mutex。這些類在構造函數中lock一個mutex,在析構函數中unlock它。因此,如果你用的是局部變量,你的mutex會在退出作用域時自動被unlock。

std::mutex m;
  my_class data;
  void foo()
  {
    std::lock_guard<std::mutex> lk(m);
    process(data);
}  // mutex unlocked here

std::lock_guard只能像上面這樣使用。而std::unique_lock允許延遲lock、設置超時,以及在對象銷毀之前unlock。如果你選擇std::timed_mutex來設置鎖超時的話,那需要使用std::unique_lock:

std::timed_mutex m;
  my_class data;
  void foo()
  {
    std::unique_lock<std::timed_mutex>
      lk(m,std::chrono::milliseconds(3)); // wait up to 3ms
    if(lk) // if we got the lock, access the data
      process(data);
}  // mutex unlocked here

由於這些lock類是模板,因此他們可以用於所有標准的mutex類型,以及提供了lock()和unlock()函數的擴展類型。

避免死鎖

有時候,我們需要鎖多個mutex。如果控制不力,可能導致死鎖(deadlock):兩個線程都試圖鎖相同的mutex,每個線程都鎖住一個mutex,而等待另外一個線程釋放其他的mutex。C++0x考慮到了這個問題,你可以使用std::lock函數來一次鎖住多個mutex,而不必冒著死鎖的危險來一個一個地鎖:

struct X
  {
    std::mutex m;
    int a;
    std::string b;
  };
  void foo(X& a,X& b)
  {
    std::unique_lock<std::mutex> lock_a(a.m,std::defer_lock);
    std::unique_lock<std::mutex> lock_b(b.m,std::defer_lock);
    std::lock(lock_a,lock_b);
    // do something with the internals of a and b
  }

在上面的例子中,如果你不使用std::lock的話,將很可能導致死鎖(如一個線程執行foo(x,y), 另一個執行foo(y,x))。加上std::lock後,則是安全的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved