C++基础之std-lock_guard/unique_lock/condition_variable[notify/wait]

      C++11的标准库中有lock这个概念,其中主要用到std::lock_guard和std::unique_lock这两把锁,unique_lock 与lock_guard都能实现自动加锁与解锁功能,但是unique_lock要比lock_guard更灵活,但是更灵活的代价是占用空间相对更大一点且相对更慢一点。unique_lock相对lock_guard更灵活的地方在于:在等待中的线程,在等待期间可以解锁mutex,并在之后可以重新将其锁定,而lock_guard却不具备这样的功能。如果有异常被抛出,unique_lock 也能被构造,以致于mutex被解锁。

       所以在一个作用域中只有一次加锁解锁操作则采用std::lock_guard,而在一个作用域中需要多次操作采用std::unique_lock。
       lock:只有在没有被上锁时,lock才能被构造;已上锁就不能被构造,一直处于等待状态,等待锁被释放。构造时上锁,析构时解锁。
       <condition_variable>下wait()进入函数时lock被解锁,当条件为false,则一直阻塞线程;当条件为true,且被触发或被执行,则退出函数,退出函数前lock被上锁。

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

#if 1
std::mutex m;
std::condition_variable cv;
bool ready = false;
bool processed = false;

void worker_thread()
{
    std::cout << "1\n";
    std::unique_lock<std::mutex> lk(m);
    std::cout << "2\n";

    cv.wait(lk, [] {return ready; }); //进入函数时lock被解锁,当条件为false,则一直阻塞线程;当条件为true,且被触发或被执行,则退出函数,退出函数前lock被上锁
    std::cout << "7\n";
    processed = true;

    lk.unlock(); //lock解锁后,上锁优先级大于构造优先级    or    wait函数先入列,所以先被调用
    std::cout << "8\n";

    getchar();
    processed = true;
    cv.notify_one();
    std::cout << "12\n";
}

int main()
{
    std::thread worker1(worker_thread);
    std::thread worker2(worker_thread);

    getchar();
    std::cout << "3\n";
 
    {
        std::lock_guard<std::mutex> lk(m); //只有在没有被上锁时,lock才能被构造;已上锁就不能被构造,一直处于等待状态,等待锁被释放。构造时上锁,析构时解锁;
        std::cout << "4\n";
        ready = true;
    }

    std::cout << "5\n";
    getchar();
    cv.notify_all();
    std::cout << "6\n";

    {
        std::unique_lock<std::mutex> lk(m); //只有在没有被上锁时,lock才能被构造,构造时上锁,析构时解锁
        std::cout << "9\n";
        cv.wait(lk, [] {return processed; });
        std::cout << "10\n";
        processed = false;
    }

    {
        std::unique_lock<std::mutex> lk(m);
        std::cout << "11\n";
        cv.wait(lk, [] {return processed; });
        std::cout << "13\n";
    }

    worker1.join();
    worker2.join();

    getchar();
    return 0;
}

#else

std::mutex m;

void worker_thread()
{
    std::unique_lock<std::mutex> lk(m);
    std::cout << "thread1" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    std::cout << "thread2" << std::endl;
    std::cout << "thread3" << std::endl;
}

int main(void)
{
    std::thread worker1(worker_thread);
    std::thread worker2(worker_thread);
    std::thread worker3(worker_thread);

    {
        std::unique_lock<std::mutex> lk(m);
        std::cout << "main" << std::endl;
        std::cout << "main" << std::endl;
        std::cout << "main" << std::endl;
    }

    getchar();
    
    //worker.join();
    return 0;
}
#endif
1
2
1
2

3
4
5

6
7
8
7
8
9
10
11

12
13

12
thread1
thread2
thread3
thread1
thread2
thread3
thread1
thread2
thread3
main
main
main



猜你喜欢

转载自blog.csdn.net/qccz123456/article/details/80271872