C++11多线程使用互斥变量

简介

在学习操作系统的时候,有学过互斥变量,也就是用来保护原子数在同一时刻只能被一个线程进行访问和修改。C++中通过实例化 std::mutex 创建互斥量,通过调用成员函数lock()进行上锁,unlock()进行解锁。不过,不推荐实践中直接去调用成员函数,因为调用成员函数就意味着,必须记住在每个函数出口都要去调用unlock(),也包括异常的情况。C++标准库为互斥量提供了一个RAII语法的模板类 std::lock_guard ,其会在构造的时候提供已锁的互斥量,并在析构的时候进行解锁,从而保证了一个已锁的互斥量总是会被正确的解锁

不加锁的情况

#include <iostream>
#include <string>
#include <thread>

using namespace std;

void function1()
{
    for(int i = 0; i < 10; i++)
    {
        cout << "From t:" << i << endl;
    }
}

int main()
{
    thread t(function1);
    for(int i = 0; i > -10; i--)
    {
        cout << "From main:" << i << endl;
    }
    t.join();
    return 0;
}

在这里插入图片描述
在不加锁的情况下,主进程main()和子进程t同时共用cout导致很混乱

使用lock()和unlock()进行加锁和解锁

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
using namespace std;

mutex mu;	//互斥变量,全局变量
void share_print(string msg, int id)
{
    mu.lock();
    cout << msg << id << endl;
    mu.unlock();
}

void function1()
{
    for(int i = 0; i < 10; i++)
    {
        //cout << i << endl;
        share_print("From t:", i);
    }
}

int main()
{
    thread t(function1);
    for(int i = 0; i > -10; i--)
    {
        //cout << i << endl;
        share_print("From main:", i);
    }
    t.join();
    return 0;
}

在这里插入图片描述可以清楚的看到,加了锁后,输出就有序了。但是这样还存在一个问题,若在解锁unlock()之前出现了异常,那就永远不会解锁,及cout就永远不会被释放,因此一般不使用lock()unlock

使用lock_guard进行互斥

std::lock_guard ,其会在构造的时候提供已锁的互斥量,并在析构的时候进行解锁,从而保证了一个已锁的互斥量总是会被正确的解锁

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
using namespace std;

mutex mu;
void share_print(string msg, int id)
{
   //mu.lock();
   lock_guard<mutex> guard(mu);
   cout << msg << id << endl;
   //mu.unlock();
}

void function1()
{
   for(int i = 0; i < 10; i++)
   {
       //cout << i << endl;
       share_print("From t:", i);
   }
}

int main()
{
   thread t(function1);
   for(int i = 0; i > -10; i--)
   {
       //cout << i << endl;
       share_print("From main:", i);
   }
   t.join();
   return 0;
}

在这里插入图片描述
加锁后有序了

总结

  1. std::mutex 和 std::lock_guard都在 头文件中声明。
  2. mutex必须为全局变量
  3. 若在解锁unlock()之前出现了异常,则被保护的变量将永远不会被释放,因此一般不用lock()unlock()

猜你喜欢

转载自blog.csdn.net/qq_36784975/article/details/88082361
今日推荐