std::lock_guard — C++最简单的线程安全锁(避免死锁)

std::lock_guard 简单用法

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

using namespace std;

int g_count = 0;
mutex g_mutex;

void increment()
{
    lock_guard<mutex> lock(g_mutex); // 开启后g_count总是可以输出20000,否则会少于20000
    ++g_count;
    this_thread::sleep_for(chrono::microseconds(2));
}

void run(int times)
{
    for (int i = 0; i < times; i++)
    {
        increment();
    }
}

int main()
{

    thread th1(run, 10000);
    thread th2(run, 10000);

    th1.join();
    th2.join();

    cout << g_count;

    return 0;
}

直接使用lock容易不对称导致死锁

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

using namespace std;

int g_count = 0;
mutex g_mutex;

int increment1()
{
    g_mutex.lock();
    this_thread::sleep_for(chrono::microseconds(1));
    g_count++;
    g_mutex.unlock();
    return 0;
}

int increment2()
{
    g_mutex.lock();
    this_thread::sleep_for(chrono::microseconds(1));
    if (g_count > 11000)
    {
        return 0;
    }
    g_count++;
    g_mutex.unlock();
    return 0;
}

void run1(int times)
{
    for (int i = 0; i < times; i++)
    {
        increment1();
    }
}

void run2(int times)
{
    for (int i = 0; i < times; i++)
    {
        increment2();
    }
}

int main()
{

    thread th1(run1, 10000);
    thread th2(run2, 10000);

    th1.join();
    th2.join();

    cout << g_count;

    return 0;
}

使用lock_guard避免死锁

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

using namespace std;

int g_count = 0;
mutex g_mutex;

int increment1()
{
    lock_guard<mutex> lock(g_mutex);
    this_thread::sleep_for(chrono::microseconds(1));
    g_count++;
    return 0;
}

int increment2()
{
    lock_guard<mutex> lock(g_mutex);
    this_thread::sleep_for(chrono::microseconds(1));
    g_count++;
    if (g_count > 11000)
    {
        return 0;
    }
    return 0;
}

void run1(int times)
{
    for (int i = 0; i < times; i++)
    {
        increment1();
    }
}

void run2(int times)
{
    for (int i = 0; i < times; i++)
    {
        increment2();
    }
}

int main()
{

    thread th1(run1, 10000);
    thread th2(run2, 10000);

    th1.join();
    th2.join();

    cout << g_count;

    return 0;
}

防止list下标越界,同样适用于map,set,vector等

#include <iostream>
#include <thread>
#include <mutex>
#include <list>

using namespace std;

class MonitorList
{

private:
    mutex g_mutex;
    list<int> g_list = {};

public:
    void push()
    {
        lock_guard<mutex> lock(g_mutex); // 不加会导致程序异常
        this_thread::sleep_for(chrono::microseconds(1));
        g_list.push_back(0);
    }

    void pop()
    {
        lock_guard<mutex> lock(g_mutex); // 不加会导致程序异常
        this_thread::sleep_for(chrono::microseconds(1));
        for (auto it = g_list.begin(); it != g_list.end(); ++it)
        {
            if (*it % 2 == 0)
            {
                it = g_list.erase(it);
            }
        }
    }
    int size()
    {
        return g_list.size();
    }
};

MonitorList g_MonitorList;

int main()
{

    thread th1([](int n)
               {
                   for (int i = 0; i < n; i++)
                   {
                       g_MonitorList.push();
                   }
               },
               10000);

    thread th2([](int n)
               {
                   for (int i = 0; i < n; i++)
                   {
                       g_MonitorList.pop();
                   }
               },
               3000);

    thread th3([](int n)
               {
                   for (int i = 0; i < n; i++)
                   {
                       g_MonitorList.pop();
                   }
               },
               3000);
    th1.join();
    th2.join();
    th3.join();

    cout << g_MonitorList.size() << endl;

    return 0;
}