C++创建多个线程、数据共享问题分析

#include <iostream>
#include <thread>
#include <vector>
using namespace std;

void myprint(int num)
{
    cout << "myprint,id:" << this_thread::get_id() << endl;
}

int main()
{
    // 创建和等待多个线程
    vector<thread> mythreads;
    // 创建10个线程,线程入口函数统一为myprint

    for (size_t i = 0; i < 10; i++)
    {
        mythreads.push_back(thread(myprint, i));
    }

    for (auto &th : mythreads)
    {
        th.join();
    }

    cout << "end main" << endl;
    return 0;
}

一、unique_lock取代lock_guard

unique_lock是个类模板,工作中,一般lock_guard(推荐使用);lock_guard取代了mutex的lockO和unlock()

unique_lock比lock_guard灵活很多;效率上差一点,内存占用多一点。

二:unique_lock的第二个参数

lock_guard可以带第二个参数:

std:lock_guard sbguard1(my_mutexl,std::adopt_lock);//adopt_.lock标记作用;

std:lock_guard sbguard1(my_mutexl,std::try_to_lock);//try_to_.lock标记作用;

(2.1)std:adopt_lock:表示这个互斥量已经被lock了(你必须要把互斥量提前lock了,否则会报异常)

std:adopt_lock标记的效果就是“假设调用方线程已经拥有了互斥的所有权(已经lock()成功了);

通知lock_guard不需要在构造函数中lock这个互斥量了;

unique_.lock也可以带std::adopt_.lock标记,含义相同,就是不希望再unique_.lock()的构造函数中lock这个mutex。

用这个adopt_lock的前提是,你需要自己先,把mutex先lock上:

(2.2)std:try_to_lock

我们会尝试用mutex的lockO去锁定这个mutex,但如果没有锁定成功,我也会立即返回,并不会阻塞在那里;

用这个txy_to_1ock的前提是你自己不能先去lock。

(2.3)std:defer_lock

用这个defer_1ock的前提是你不能自己先lock,否则会报异常。

defer_lock的意思就是并没有给mutext加锁:初始化了一个没有加锁的mutex

三、unique_lock的成员函数

std::unique_lock ulock(my_mutex,std::defer_lock);//没有加锁的my_mutex

ulock.lock();//不需要自己解锁

(3.1)1ock(),加锁

(3.2)unlock(),解锁;

(3.3)txy_lock(),尝试给互斥量加锁,如果拿不到锁,则返回false,如果拿到了锁,返回true,这个函数不阻塞的;

(3.4)release(),返回它所管理的mutex指针,并释放所有权;也就是说,这个unique_lock和mutex不再有关系。

严格区分unlock()和release()的区别,不要混淆

如果原来mutex对象处于加锁状态,我们有责任接管过来手动解锁。(release返回的是原始mutex的指针)

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

mutex m;
void myprint(int num)
{
    std::unique_lock<std::mutex> g(m);
    std::mutex *pmtx = g.release(); // release后,需要我们自己解锁这个m
    cout << "myprint,id:" << this_thread::get_id() << endl;
    pmtx->unlock(); // 自己解锁
    delete pmtx;
    pmtx = nullptr;
}

int main()
{
    // 创建和等待多个线程
    vector<thread> mythreads;
    // 创建10个线程,线程入口函数统一为myprint

    for (size_t i = 0; i < 10; i++)
    {
        mythreads.push_back(thread(myprint, i));
    }

    for (auto &th : mythreads)
    {
        th.join();
    }

    cout << "end main" << endl;
    return 0;
}

四、unique_lock所有权的传递

unique_lock需要管理一个mutex

unique_lock ulock(my_mutex);所有权概念

ulock拥有my_mutex的所有权

ulock可以把自己对my_mutext的所有权转移给其它的unique_lock对象;

所以,unique_lock对象这个mutex的所有权是属于 可以转移,但是不能复制的

unique_lock ulock(my_mutex);

unique_lock ulock2(my_mutex); //报错,不能复制

unique_lock ulock(move(my_mutex)); //对的

std::unique_lock<std::mutex> get_unique_lock()
{
    std::unique_lock<std::mutex> tmp(m);
    return tmp; // 从函数返回一个局部的unique_lock对象时可以的.返回这种局部对象tmp会导致系统生成临时unique_lock对象,并调用unique_lock的移动构造函数
}

从函数返回一个局部的unique_lock对象时可以的.返回这种局部对象tmp会导致系统生成临时unique_lock对象,并调用unique_lock的移动构造函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值