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);
}

 

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