c++多線程, lock/try_lock/once_flag/ call_once

std::lock

template<class Mutex1, class Mutex2, class ... Mutexes>

    void lock(Mutex1& a, Mutex2& b, Mutexes&... cde);

鎖定作爲參數傳進來的對象,如果有必要調用線程進行阻塞;

std::lock通過使用lock、try_lock、unlock來鎖定對象,返回之前確保所有的對象都上鎖,並且沒有產生死鎖

如果不能鎖定所有對象,在失敗之前會前之前成功鎖定的對象解鎖;

#include <iostream>
 #include <mutex>
 #include <thread>
 
 using namespace std;
 
 mutex foo, bar;
 void TaskA() {
     lock(foo, bar);
     cout<<"TaskA "<<endl;
     foo.unlock();
     bar.unlock();
 }
 
 void TaskB() {
     lock(bar, foo);
     cout<<"TaskB"<<endl;
     bar.unlock();
     foo.unlock();
 }
 
 int main(void) {
     thread threads[2];
     threads[0] = thread(TaskA);
     threads[1] = thread(TaskB);
     for (int i = 0; i < 2; ++i) {
         threads[i].join();
     }
     return 0;
 }

 要注意,可能會產生死鎖

Note that before replacing the individual locks by the call to std::lock, if task_a locked foo while task_b locked bar, neither could ever get the second lock, causing a deadlock.

std::try_lock

template<class Mutex1, class Mutex2, class... Mutexes>

    int try_lock(Mutex1& a, Mutex2& b, Mutexes... cde);

Attempts to lock all the objects passed as arguments using their try_lock member functions (non-blocking).

返回值:

如果都成功鎖住則返回-1,否則返回失敗加鎖的對象index,0 for a, 1 for b, ...;

#include <iostream>
 #include <mutex>
 #include <thread>
 
 using namespace std;
 
 mutex foo, bar;
 
 void TaskA() {
     foo.lock();
     cout<<"Task A"<<endl;
     bar.lock();
     //
     foo.unlock();
     bar.unlock();
 }
 
 void TaskB() {
     int x = try_lock(bar, foo);
     if (x == -1) {
         cout<<"task b"<<endl;
         foo.unlock();
         bar.unlock();
     } else {
         cout<< "task b failed: mutex"<<(x ? "foo" :\
                 "bar ")<<" locked"<<endl;
     }
 }
 
 int main(void) {
     thread t1(TaskA);
     thread t2(TaskB);
 
     t1.join();
     t2.join();
     return 0;
 }

要注意:

Either mutex may appear locked to task_b, or both tasks may succeed in either order (text can appear intermingled on failure).

std::once_flag;

Flag argument tyep for call_once;

once_flag作爲call_once的參數

struct once_flag {
    constecxpr once_flag() noexcept;
    once_flag(const once_flag&) = delete;
    once_flag& operator=(const once_flag&) = delete;
};

std::call_once

template<class Fn, clas... Args>

    void call_once(once_flag& flag, Fn&& fn, Args&&... args);

int winner;
void SetWinner(int x) {
    winner = x;
}
std::once_flag winner_flag;

void WaitThousandSeconds(int id) {
    for (int i = 0; i < 1000; ++i) {
        std::this_thread.::sleep_for(std::chrono::milliseconds(1));
    }
    std::call_once(winner_flag, SetWinner, id);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章