87 C++线程同步

文章详细介绍了C++11中的线程同步方法,包括互斥锁(mutex)及其变体如带超时的互斥锁和递归互斥锁。互斥锁用于保证同一时间只有一个线程访问共享资源,通过lock()、unlock()和try_lock()进行操作。还提到了递归互斥锁允许同一线程多次加锁,以及lock_guard类如何通过RAII原则简化互斥锁的使用,确保资源安全释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程同步是指多个线程协同工作,协商如何使用共享资源。

C++11线程同步包括三个方面的内容

  • 互斥锁(互斥量)
  • 条件变量
  • 生产者/消费者模型

互斥锁:

加锁和解锁,确保同一时间只有一个线程访问共享资源

访问共享资源之前加锁,访问完成后释放锁。

如果某线程持有锁,其它线程形成等待队列。

C++11提供了四种互斥锁:

1 mutex:互斥锁。

2 timed_mutex:带超时机制的互斥锁。

3 recursive_mutex:递归互斥锁。

4 recursive_timed_mutex:带超时机制的递归互斥锁。

包含头文件:#include

mutex类

1)加锁lock()

互斥锁有锁定和未锁定两种状态。

如果互斥锁是未锁定状态,调用lock()成员函数的线程会得到互斥锁的所有权,并将其上锁。

如果互斥锁是锁定状态,调用lock()成员函数的线程就会阻塞等待,直到互斥锁变成未锁定状态。

2)解锁unlock()

只有持有锁的线程才能解锁。

3)尝试加锁try_lock()

如果互斥锁是未锁定状态,则加锁成功,函数返回true。

如果互斥锁是锁定状态,则加锁失败,函数立即返回false。(线程不会阻塞等待)

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

int aa = 0;

mutex mtx;

void func()
{
    for (int i = 0; i < 1000000; i++)
    {
        cout << "线程:" << this_thread::get_id() << "申请加锁..." << endl;
        mtx.lock();
        cout << "线程:" << this_thread::get_id() << "加锁成功" << endl;
        aa++;
        this_thread::sleep_for(chrono::seconds(5));
        mtx.unlock();
        cout << "线程:" << this_thread::get_id() << "释放了锁" << endl;
        this_thread::sleep_for(chrono::seconds(1));
    }
}
void test()
{
    thread t1(func);
    thread t2(func);
    t1.join();
    t2.join();
    cout << "aa=" << aa << endl;
}
int main()
{
    test();
    return 0;
}
/* .....
线程:2释放了锁
线程:3加锁成功
线程:2申请加锁...
线程:3释放了锁
线程:2加锁成功
线程:3申请加锁...
线程:2释放了锁
..... */

timed_mutex类

增加了两个成员函数:

bool try_lock_for(时间长度);

bool try_lock_until(时间点);

recursive_mutex类

递归互斥锁允许同一线程多次获得互斥锁,可以解决同一线程多次加锁造成的死锁问题。

#include <iostream>
#include <mutex>
using namespace std;
class AA
{
    // mutex m_mtx;//本demo直接用mutex会发生死锁
    recursive_mutex m_mtx;

public:
    void func1()
    {
        m_mtx.lock();
        cout << "func1" << endl;
        m_mtx.unlock();
    }
    void func2()
    {
        m_mtx.lock();
        cout << "func2" << endl;
        func1();
        m_mtx.unlock();
    }
};
void test()
{
    AA a;
    // a.func1();
    //死锁,普通的互斥锁必须在解锁后才能加锁,就算是同一个线程也不能例外.这时候可以用 recursive_mutex
    a.func2();
}
int main()
{
    test();
    return 0;
}

死锁,普通的互斥锁必须在解锁后才能加锁,就算是同一个线程也不能例外.这时候可以用recursive_mutex

lock_guard类

lock_guard是模板类,可以简化互斥锁的使用,也更安全

lock_guard的定义如下:

template

class lock_guard

{

explicit lock_guard(Mutex& mtx);

}

lock_guard在构造函数中加锁,在析构函数中解锁。

lock_guard采用了RAII思想(在类构造函数中分配资源,在析构函数中释放资源,保证资源在离开作用域时自动释放)。智能指针也是采用RAII思想。

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

int aa = 0;

mutex mtx;

void func()
{
    for (int i = 0; i < 1000000; i++)
    {
        lock_guard<mutex> lockguard(mtx);
        aa++;
    }
}
void test()
{
    thread t1(func);
    thread t2(func);
    t1.join();
    t2.join();
    cout << "aa=" << aa << endl;
}
int main()
{
    test();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值