C++多线程

多线程:

thread_local

每个线程都会有自己的一份数据,不会共享数据,避免竞争

 

volatile

告诉编译器每次取数据都要从内存里取

 

使用情况:

  1. 信号处理
  2. 内存映射相关
  3. 非本地跳转

 

std::atomic

定义操作为原子操作,不可被线程分开

 

接口

 

 

std::shread C++的线程类,但是不保证异步。std::async可以强制异步,可以指定两种异步方式:  std::launch::async(使用新的线程异步执行任务)std::launch::deferred(用当前线程执行,时间上会延后)

 

如果需要在调用线程和新线程之间同步数据可以用promisefuture

std::promise

其作用是在一个线程t1中保存一个类型typename T的值,可供相绑定的std::future对象在另一线程t2中获取。

 

std::future

可以用来获取异步任务的结果,因此可以把它当成一种简单的线程间同步的手段std::future对象通常通过某个Provider创建,Provider在某个线程中设置共享状态的值,与该共享状态相关联的std::future对象通过get获得该值,如果该装填不为ready,则std::future::get会阻塞当前调用的人,知道Provider设置了共享状态的值为readyget会返回异步任务的值或异常。

 

实例:

#include <iostream>

#include <future>

#include <chrono>

 

void Thread_Fun1(std::promise<int> &p)

{

//为了突出效果,可以使线程休眠5s

std::this_thread::sleep_for(std::chrono::seconds(5));

 

int iVal = 233;

std::cout << "传入数据(int):" << iVal << std::endl;

 

//传入数据iVal

p.set_value(iVal);

}

 

void Thread_Fun2(std::future<int> &f)

{

//阻塞函数,直到收到相关联的std::promise对象传入的数据

auto iVal = f.get(); //iVal = 233

 

std::cout << "收到数据(int):" << iVal << std::endl;

}

 

int main()

{

//声明一个std::promise对象pr1,其保存的值类型为int

std::promise<int> pr1;

//声明一个std::future对象fu1,并通过std::promise的get_future()函数与pr1绑定

std::future<int> fu1 = pr1.get_future();

 

//创建一个线程t1,将函数Thread_Fun1及对象pr1放在线程里面执行

std::thread t1(Thread_Fun1, std::ref(pr1));

//创建一个线程t2,将函数Thread_Fun2及对象fu1放在线程里面执行

std::thread t2(Thread_Fun2, std::ref(fu1));

 

//阻塞至线程结束

t1.join();

t2.join();

 

return 1;

}

 

C++20支持协程

 

std::mutex 互斥量,表示之后的代码段同时只能由一个线程访问

lock_guard是一种在作用域内可以控制可锁对象所有权的类型

特点:

(1) 创建即加锁,作用域结束自动析构并解锁,无需手工解锁
(2) 不能中途解锁,必须等作用域结束才解锁
(3) 不能复制

std::unique_lock 可以实现尝试获得锁, 如果当前以及被其它线程锁定, 则延迟直到其它线程释放, 然后才获得锁.

特点:

(1) 创建时可以不锁定(通过指定第二个参数为 std::defer_lock),而在需要时再锁定

(2) 可以随时加锁解锁

(3) 作用域规则同 lock_grard,析构时自动释放锁

(4) 不可复制,可移动

(5) 条件变量需要该类型的锁作为参数(此时必须使用 unique_lock

 

std::mutex g_mutex;

std::lock_guard<std::mutex> guard(g_mutex);//可以及时进入和释放互斥量

实例:

#include <chrono>

#include <thread>

#include <mutex>

 

bool flag;

std::mutex m;

 

void wait_for_flag()

{

    std::unique_lock<std::mutex> lk(m); // 这里采用std::unique_lock而非std::lock_guard. std::unique_lock可以实现尝试获得锁, 如果当前以及被其它线程锁定, 则延迟直到其它线程释放, 然后才获得锁.

    while(!flag)

    {

        lk.unlock(); // 解锁互斥量

        std::this_thread::sleep_for(std::chrono::milliseconds(100));  // 休眠100ms,在此期间,其它线程可以进入互斥量,以便更改flag标记。

        lk.lock();   // 再锁互斥量

    }

}

 

 

std::condition_variable(条件变量)

 

源自博客:https://blog.csdn.net/qq_23350817/article/details/116460138

posted @ 2023-05-27 11:20  Pireannn  阅读(59)  评论(0)    收藏  举报