当前位置: 首页 > news >正文

48. c++线程

c++多线程实现使用标准库中的<thread>,一下代码描述多线程实现方式 ,最简单的线程创建方式是通过传递一个可调用对象(如函数指针、函数对象或 Lambda 表达式)

48.1 线程创建与使用

 以下代码展示通过传递lambda表达式和函数指针给线程对象的方式,线程对象worker一直打印working直到控制台按下enter建结束。

//
//  main.cpp
//  HelloWorld
//
//  Created by lxr on 2024/11/28.
//

#include <iostream>
#include <vector>
#include <thread>
static bool ifFinished = false;
void doWork()
{
    using namespace std::literals::chrono_literals;
    std::cout<<"start thread id="<<std::this_thread::get_id()<<std::endl;
    while (!ifFinished) {
        std::cout<<"working.."<<std::endl;
        std::this_thread::sleep_for(1s);
    }
}
int main(int argc, const char * argv[]) {
    // insert code here...
    //lambda表达式给线程传递对象
    std::thread th([](int a){
        std::cout<<"lambda thread"<<std::endl;
    });
    //函数指针给线程传递对象
    std::thread worker(doWork);
    std::cin.get();
    ifFinished = true;
    worker.join();//类似其他语言中的wait,等待worker子线程结束后才继续后续代码
    std::cout<<"finished"<<std::endl;
    std::cout<<"start thread id="<<std::this_thread::get_id()<<std::endl;
    std::cin.get();
}

 

48.2 线程生命周期

std::thread在其对象超出作用域时会自动销毁,如果线程对象没有显示的调用join或detach,则程序会有异常,导致程序终止:

void create_thread() {
	std::thread t([]() { std::cout << "Hello from thread!" << std::endl; });
	// 这里没有调用 t.join() 或 t.detach(),会导致程序终止
}
int main(int argc, const char * argv[]) {
	create_thread();
}

 

join()

  • join() 方法用于等待线程完成。如果你在主线程中调用 join(),则主线程会暂停执行,直到目标线程执行完毕。
  • 调用 join() 是线程生命周期的正确结束方式,确保线程资源得到了适当的清理

detach()

  • detach() 方法用于将线程与当前执行流分离。这意味着线程将会在后台继续执行,且主线程不会等待它完成。被分离的线程将会在完成后自动清理资源。
  • 要确保分离的线程没有在主线程结束之前完成执行

 为了避免异常,应该始终在使用完线程后,显式地调用 join()detach()

48.3 互斥

 多线程并发时,要处理资源竞争的问题,为了确保共享资源数据的准确性,需要给线程加锁:

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

std::mutex mtx;  // 互斥锁
int counter = 0;

void threadFunction(int threadID) {
	std::lock_guard<std::mutex> guard(mtx);  // 自动加锁
	std::cout << "threadID:" << threadID << " counter:" << counter++ << " id:" << std::this_thread::get_id() << std::endl;
}

int main() {
	std::vector<std::thread> threads;
	for (int i = 0; i < 100; ++i)
	{
		threads.emplace_back(threadFunction, i);
	}
	for (int i = 0; i < threads.size(); ++i)
	{
		threads.at(i).join();
	}
	std::cout << "final counter: " << counter << std::endl;
	return 0;
}

加锁后的共享资源counter会依次递增,数据准确 

 

 将加锁代码std::lock_guard<std::mutex> guard(mtx);注释后发现counter增加混乱,数据准确性会被破坏

此外还可以使用std::unique_lock<std::mutex> lock(mtx);进行加锁,可以灵活加锁和解锁,但开销较大,在一般情况下优先使用std::lock_guard

相关文章:

  • Linux-文件基本操作1
  • 空间复杂度O(m) O(n) O是什么,m是什么,n是什么
  • 使用多种机器学习算法进行鸢尾花分类
  • Deepseek本地部署和网页版本区别
  • Redis 的缓存雪崩、缓存穿透和缓存击穿详解,并提供多种解决方案
  • 据称苹果与阿里巴巴将合作为中国iPhone用户开发AI功能
  • 第一章:认识Tailwind CSS - 第一节 - Tailwind CSS 的核心理念
  • DBeaver clickhouse 时区不对 时间少了8小时
  • 【广州大学主办,发表有保障 | IEEE出版,稳定EI检索,往届见刊后快至1个月检索】第二届电气技术与自动化工程国际学术会议 (ETAE 2025)
  • 8、《5分钟构建RESTful API:Spring Boot Web开发入门》
  • 本地部署DeepSeek后的调用与删除全攻略
  • 计算机网络知识速记:TCP 与 UDP
  • 在 debian 12 上安装 mysqlclient 报错
  • Gemini Thinks Faster
  • 10 . Docker 中的 DockerFile 解析(各种指令说明)
  • 安装mysql5.7报错 mysqld.exe-系统错误 由于找不到MSVCP120.dll,无法继续执行代码。重新安装程序可能 会解决此问题。 确定
  • /etc/sysctl.conf——系统的配置文件
  • #define宏与编译时定义的本质对决:从const常量到typedef的类型安全演进
  • 第二章:基础概念精讲 - 第一节 - Tailwind CSS 响应式设计系统
  • Okay, But Please Don’t Stop Talking
  • 前4个月全国新建商品房销售面积降幅收窄,房地产库存和新开工有所改善
  • 网络直播间销售玩具盲盒被指侵权,法院以侵犯著作权罪追责
  • 以色列在加沙发起新一轮强攻,同步与哈马斯展开“无条件谈判”
  • 十年牢狱倒计时,一名服刑人员的期待与惶恐
  • 经济日报:人工智能开启太空经济新格局
  • 人形机器人灵犀X2掌握新技能:有了“内心戏”,还会拳脚功夫