首页 > 编程语言 >c++多线程

c++多线程

时间:2024-03-08 14:35:24浏览次数:28  
标签:detach join thread int void c++ 线程 多线程

1. 线程库的使用

创建进程

# include<iostream>
# include<thread> //线程库头文件

using namespace std;

void thread_1()
{
    cout<<"子线程1"<<endl;
}

int thread_2(int x)
{
    cout<<"子线程2"<<endl;
    return x;
}


int main()
{

    //thread函数创建一个新线程
    //first是线程名,括号里第一个参数是函数名,第二个参数是给第一个函数的参数
    thread first(thread_1); 
    thread second(thread_2 , 100);
    
    //若没有下面这两行,程序会报错
    //因为若没有下面这两行程序会一直执行下去。
    //很有可能在主线程return 0后,子线程还没有继续进行
    first.detach();
    second.join();

    return 0;
}

join和detach

first.join(); //主进程会等待子进程first执行完毕后才继续执行
second.detach(); //主进程不会等待子进程,子线程在后台运行

joinable

判断线程是否可以join,返回bool类型

若对一个不能使用join或detach的线程强行使用join或detach会报一个system_error

所以在一个比较严谨的项目中会先判断一下是否可以使用

int main()
{
    thread first(thread_1);
    thread second(thread_2 , 100);
    first.detach();
    //second.detach();
    if(second.joinable()) 
    {
        second.join();
    }
    cout<<"主进程";
    return 0;
}

2. 互斥锁mutex(互斥量)

如下面的代码

当两个线程都对一个全局变量进行操作时候。若a = 3,两个线程恰好在同一时刻执行a++,那么a会等于4而不是我们下意识想到的5

为了避免这个情况,我们使用互斥锁mutex

当线程遇到lock()
若没上锁,则上锁,其他线程无法访问
若已上锁,则等待解锁

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

using namespace std;

int a = 1;
mutex mtx;

void f()
{
    for(int i=1;i<=1000;i++)
    {
        mtx.lock();   //上锁
        a++;
        mtx.unlock();  //解锁
    }
}

int main()
{
    thread t1(f);
    thread t2(f);
    t1.join();t2.join();

    cout<<a;
    return 0;
}

3. 原子操作

原子操作就是: 不可中断的一个或者一系列操作, 也就是不会被线程调度机制打断的操作, 运行期间不会有任何的上下文切换(context switch).

讲第二个例子中的a改成atomic 类型,删去锁操作依旧可以达到相同的目的,实现线程安全

atomic<int> a = 1

void f()
{
    for(int i=1;i<=1000;i++)
    {
        a++;
    }
}

int main()
{
    thread t1(f);
    thread t2(f);
    t1.join();t2.join();

    cout<<a;
    return 0;
}

4. 互斥量死锁

下面的两个线程可能会发生死锁:
f1占有m1资源,f2占有m2资源,然后两个都在等待对方释放资源

mutex m1;
mutex m2;
void f1()
{
    for(int i=1;i<=1000;i++)
    {
        m1.lock();
        m2.lock();
        m1.unlock();
        m2.unlock();
    }
}

void f2()
{
    for(int i=1;i<=1000;i++)
    {
        m2.lock();
        m1.lock();
        m1.unlock();
        m2.unlock();
    }
}

只需要将f2改成下面这样就好了

void f2()
{
    for(int i=1;i<=1000;i++)
    {
        m1.lock();
        m2.lock();
        m1.unlock();
        m2.unlock();
    }
}

5. unique lock

实现自动解锁

int a = 1;
mutex mtx;

void f()
{
    for(int i=1;i<=1000;i++)
    {
        unique_lock<mutex>lg(mtx);  
        a++;
    }
}

int main()
{
    thread t1(f);
    thread t2(f);
    t1.join();t2.join();

    cout<<a;
    return 0;
}

标签:detach,join,thread,int,void,c++,线程,多线程
From: https://www.cnblogs.com/algoshimo/p/18060888

相关文章

  • C++中的static关键字
    在C++中,static是一个关键字,用于声明静态变量、静态函数、静态类成员以及静态局部变量。static关键字的作用取决于它所修饰的上下文,以下是static关键字的几种常见用法:静态变量:在函数内部使用static关键字声明的变量称为静态局部变量。静态局部变量的生命周期延长到整个程......
  • C++中OpenCV、Armadillo矩阵数据格式的转换方式
      本文介绍在C++语言中,矩阵库Armadillo的mat、vec格式数据与计算机视觉库OpenCV的Mat格式数据相互转换的方法。  在C++语言的矩阵库Armadillo与计算机视觉库OpenCV中,都有矩阵格式的数据类型;而这两个库在运行能力方面各有千秋,因此实际应用过程中,难免会遇到需要将二者的矩阵格......
  • C++中的volatile关键字
    在C++中,volatile是一个关键字,用于告诉编译器,该变量的值可能会在未知的时刻被意外地改变,因此编译器对于该修饰的变量的操作时应该保持对该变量内存地址的直接内存访问操作,而不应对访问该变量的代码进行任何优化。。volatile关键字的主要作用是告诉编译器不要对该变量进行优化,......
  • C++ Qt开发:QFileSystemModel文件管理组件
    Qt是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍如何运用QFileSystemModel组件实现文件管理器功能。QFileSystemModel是Qt框架中的一个关键类,用于......
  • 复试C++ 异常 看程序写结果
    就算每一个case后面都没有break,throw相当于起了break的作用?#include<iostream>#include<stdexcept>usingnamespacestd;classErrorA:publicruntime_error{public:ErrorA():runtime_error{"errorAAAA"}{}};classErrorB:publicruntime_erro......
  • Unity3D 多线程定时器的原理与实现详解
    Unity3D提供了丰富的功能和工具,让开发者可以轻松地创建各种类型的游戏。其中,定时器是一个非常重要的功能,在游戏开发中经常会被使用到。Unity3D中并没有提供原生的多线程定时器功能,但我们可以通过一些技巧和方法来实现一个多线程定时器。对啦!这里有个游戏开发交流小组里面聚集了......
  • C++入门编程----C++运算符(8)
    什么是运算符运算符是让程序执行特定的数学或逻辑操作的符号,用来表示针对数据的特定操作,也称之为操作符。C++运算符分别有算术运算符、关系运算符、逻辑运算符、赋值运算符、位运算符、移位运算符、sizeof运算符、三目运算符、逗号运算符和域解析运算符。算术运算符C++中的算术......
  • c++ lambda表达式
    引入lambda表达式也有人称之为匿名函数,能够在任何作用域下快速定义一个函数下面这行代码就是一个最简单的lambda表达式,最后输出为3autof=[](intx,inty)->int{returnx+y;};cout<<f(1,2);我们来解析一下lambda表达式autof=[](intx,inty)->int{returnx+y;};......
  • C++保证线程安全的方式
    1、互斥量可以确保同一时间只有一个线程访问临界区,防止出现竞态条件。2、原子操作std::atomic<int>mutex(1);对原子变量的操作是线程安全的。3、读写锁std::shared_mutexmutex;//读者:共享锁定mutex.lock_shared();mutex.unlock_shared();//写者:独占锁定mutex.lock......
  • c/c++指针中 * 和 & 的区别与联系
    在C语言中,*和&是两个非常基础但功能相反的操作符,它们分别是解引用(dereference)操作符和取地址(address-of)操作符。&(取地址操作符)用途:&操作符用来获取变量的内存地址。示例:假设有一个整型变量intx=10;,则&x表示获取变量x的内存地址。如果你有一个指针变量想要存储变量x的地址,可......