#include <future>
#include <mutex>
#include <iostream>
#include <string>
#include <exception>
#include <stdio.h>
using namespace std;

mutex printMutex;
static string s = "Hello from a first thread";
void print()
{
    try{
        cout << "thread start:" << this_thread::get_id() << endl;
        lock_guard<mutex> l(printMutex);//它只能保证你的thread不能并发(在printMutex没有释放前,它可以阻塞其他的调用),但是后面的s数据可以被改变
        /*这样的lock应该被限制在可能之最短周期内,因为它们会阻塞(block)其他代码的并行运行机会。由于析构
        函数会释放这个lock,你或许会想明确安插大括号,令lock在更近一步语句被处理前先被释放*/
        for (char c : s)
        {
            this_thread::sleep_for(chrono::milliseconds(500));
            cout.put(c);
        }
        cout << endl;
    }
    catch (const exception& e)
    {
        cerr << "EXCEPTION: " << e.what() << endl;
    }
}

int main()
{
    try{
        
        auto f1 = async(launch::async, print);
        s = "Hello from a second thread";
        auto f2 = async(launch::async, print);
        this_thread::sleep_for(chrono::milliseconds(20000));
        s = "Hello from the main thread";
        print();
    }
    catch (const exception& e)
    {
        cerr << "EXCEPTION: " << e.what() << "  On Main " << endl;
    }
    system("pause");
    return 0;
}

 有时候我们会遇到这种情况:

当我们定义一个类,我们定义了private 的mutex 变量。并且在类里的函数中进行了锁定(lock_guard<mutex>lg(变量))。当我们在某个函数中进行锁定mutex 变量,并且我们在其后面调用了我们有锁定变量的类函数。

这样会造成死锁的情况出现。因为我们已经锁住了mutex 变量,但是后面的语句中我们还要锁定mutex 变量,所以第二次锁定的mutex 变量要等待第一次mutex 变量解锁,但是该函数没有运行完第一次锁定的mutex 变量不会被析构函数将这个lock释放掉,所以线程一直在等待,造成死锁。

解决方案:我们可以使用recursive_mutex 来进行定义mutex变量。

recursive_mutex允许同一线程多次锁定,并在最近的一次(last)相应的unlock时释放lock。