多线程 —— 线程控制

news2025/2/21 19:29:22

目录

    • 线程控制
      • 1 线程创建
      • 2 线程等待
      • 3 线程终止
      • 4 线程分离
    • pthread_t id && LWP

线程控制

1 线程创建

功能:创建一个新的线程
原型
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)
(void*), void *arg);
参数
thread:返回线程ID
attr:设置线程的属性,attr为NULL表示使用默认属性
start_routine:是个函数地址,线程启动后要执行的函数
arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *thread_run(void *args){
  while(1){
    //printf("我是新线程[%s],我创建的线程ID是:%lu\n", (const char*)args, pthread_self());
    sleep(1);
  }
  
}
int main(){
   
  pthread_t tid[5];
  int i;
  for(i = 0; i < 5; i++){
    pthread_create(tid+i, NULL, thread_run, (void *)"new thread");
  }

  while(1){

    printf("我是主线程,我的thread ID:%lu\n", pthread_self());
    printf("##############################begin#########################\n");
    for(i = 0; i < 5; i++){
      printf("我创建的线程[%d]是:%lu\n", i, tid[i]);
    }
    printf("###############################end##########################\n");
    sleep(1);
  }
}

image-20230529160615954

2 线程等待

一般而言,线程也是需要等待的,如果不等待,可能会导致类似于“僵尸进程”的问题!

用下面这个函数实现等待

image-20230529211448152

举个例子:

下面这个程序会因为单个线程的野指针问题而造成所有线程崩溃

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *thread_run(void *args){
  int num = *(int*)args;
  while(1){
    //printf("我是新线程[%s],我创建的线程ID是:%lu\n", (const char*)args, pthread_self());
    sleep(1);
    //野指针问题,测试一个线程崩整个进程则崩的问题
    if(num == 3){
      printf("thread number: %d quit\n", num);
      int *p = NULL;
      *p = 1000;
    }
  }
  
}

#define NUM 5

int main(){
   
  pthread_t tid[NUM];
  int i;
  for(i = 0; i < NUM; i++){
    pthread_create(tid+i, NULL, thread_run, (void *)&i);
    sleep(1);
  }

  while(1){

    printf("我是主线程,我的thread ID:%lu\n", pthread_self());
    printf("##############################begin#########################\n");
    for(i = 0; i < NUM; i++){
      printf("我创建的线程[%d]是:%lu\n", i, tid[i]);
    }
    printf("###############################end##########################\n");
    sleep(1);
  }
  return 0;
}

运行结果

image-20230529211559468

  • 使用pthread_join进行线程等待
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void *thread_run(void *args){
  int num = *(int*)args;
  while(1){
    printf("我是新线程[%s],我创建的线程ID是:%lu\n", (const char*)args, pthread_self());
    sleep(1);
    break;
    //野指针问题,测试一个线程崩整个进程则崩的问题
    //if(num == 3){
    //  printf("thread number: %d quit\n", num);
    //  int *p = NULL;
    //  *p = 1000;
    //}
  }
  //退出异常,不需要处理
  //这里的返回值也可以是其他变量,不一定为int型,但不能是临时的
  return (void*)111;  
}

#define NUM 1

int main(){
   
  pthread_t tid[NUM];
  int i;
  for(i = 0; i < NUM; i++){
    pthread_create(tid+i, NULL, thread_run, (void *)&i);
    sleep(1);
  }

  //void* 32.4 64.8, 指针变量。本身就可以充当某种容器保存数据
  void *status = NULL;
  //退出信息
  pthread_join(tid[0], &status);

  printf("ret: %d\n", (int)status);
//while(1){

  //  printf("我是主线程,我的thread ID:%lu\n", pthread_self());
  //  printf("##############################begin#########################\n");
  //  for(i = 0; i < NUM; i++){
  //    printf("我创建的线程[%d]是:%lu\n", i, tid[i]);
  //  }
  //  printf("###############################end##########################\n");
  //  sleep(1);
  //}
  return 0;
}

image-20230529213110071

image-20230529213349877

线程出异常,pthread_join不需要处理,这是进程的问题

3 线程终止

  1. 函数中return

    image-20230529214306808

  2. pthread_exit

    新线程通过pthread_exit终止自己(vs exit是终止进程,只想终止一个线程时不要调用)

    image-20230529214615101

    image-20230529214546540

  3. pthread_cancel

    直接发起一个请求给目标进程,即取消目标线程

    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    
    void *thread_run(void *args){
      int num = *(int*)args;
      while(1){
        printf("我是新线程[%s],我创建的线程ID是:%lu\n", (const char*)args, pthread_self());
        sleep(2);
        //break;
        //野指针问题,测试一个线程崩整个进程则崩的问题
        //if(num == 3){
        //  printf("thread number: %d quit\n", num);
        //  int *p = NULL;
        //  *p = 1000;
        //}
      }
      //线程出异常不需要处理
      //这里的返回值可以是其他变量,并非只能int,但不能是临时变量
      
      //pthread_exit((void*)123);
      //return (void*)111;  
    }
    
    #define NUM 1
    
    int main(){
       
      pthread_t tid[NUM];
      int i;
      for(i = 0; i < NUM; i++){
        pthread_create(tid+i, NULL, thread_run, (void *)&i);
        sleep(1);
      }
      printf("wait sub thread...\n");
      sleep(5);
      printf("cancel sub thread....\n");
      pthread_cancel(tid[0]);
    
      //void* 32.4 64.8, 指针变量。本身就可以充当某种容器保存数据
      void *status = NULL;
      pthread_join(tid[0], &status);
    
      printf("ret: %d\n", (int)status);
      sleep(3);
    //while(1){
    
      //  printf("我是主线程,我的thread ID:%lu\n", pthread_self());
      //  printf("##############################begin#########################\n");
      //  for(i = 0; i < NUM; i++){
      //    printf("我创建的线程[%d]是:%lu\n", i, tid[i]);
      //  }
      //  printf("###############################end##########################\n");
      //  sleep(1);
      //}
      return 0;
    }
    

    运行结果,可以发现,取消线程,退出码为-1

    image-20230529220110654

    可以用其他线程取消主线程,但此时可能会造成僵尸进程问题,此时里面还可能有子线程在运行。

4 线程分离

image-20230529221652719

分离之后的线程不需要被join,运行完毕之后,会自动释放Z,pcb。
一般都是自己分离自己,也可以主线程分离新线程。
一个线程被设置分离之后,就不能再被join了。

pthread_t id && LWP

我们查看到的线程id是pthread库的线程id,不是Linux内核中的LWP,pthread库的线程id是一个内存地址!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/596007.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python中任取一个数

Python中任取一个数 如果你是一名Python编程爱好者或者是从事相关行业的工程师&#xff0c;你可能会知道Python强大的数学计算能力。Python中自带了诸多数学函数和库&#xff0c;例如NumPy、SciPy、pandas等等&#xff0c;可以帮助我们轻松地完成各种计算任务&#xff0c;包括…

MySQL—存储引擎(上)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️树高千尺&#xff0c;落叶归根人生不易&…

Ae 脚本:Face Tools 4 脸部工具

Motion Bro 的 AE Face Tools 扩展脚本工具&#xff0c;包含几百种预设&#xff0c;如换脸、换妆、美颜、液化、失真扭曲、面部修饰、蒙板工具、文字跟踪、添加元素、人脸锁定防抖稳定以及遮挡等预设效果&#xff0c;大大扩展了 After Effects 中的人脸跟踪功能。 AE Face Tool…

基于激光雷达和单目视觉融合的SLAM和三维语义重建

文章&#xff1a;SLAM and 3D Semantic Reconstruction Based on the Fusion of Lidar and Monocular Vision 作者&#xff1a;Lu Lou, Yitian Li, Qi Zhang and Hanbing Wei 编辑&#xff1a;点云PCL 欢迎各位加入知识星球&#xff0c;获取PDF论文&#xff0c;欢迎转发朋友圈。…

领导说培养我,怎么看出来他是真培养,还是PUA我?

当你的领导说要培养你的时候&#xff0c;如何分辨他的真实意图&#xff1f; 一位网友问&#xff1a; 领导说培养我&#xff0c;怎么看出来他是真培养&#xff0c;还是PUA&#xff1f; 来看看这位网友的支招&#xff1a; 如果领导做到以下几点&#xff0c;那就是真的培养你。 1.…

实战记录01(QT连接MySQL显示未加载问题解决)

进入实战 学了这么几天就要开发新项目了&#xff0c;所以可能不会每日记录吧&#xff0c;遇到问题可能就发一下&#xff0c; 昨天是又重新写了一个登录和管理界面&#xff0c;写完之后就可以开始链接数据库了。 QT连接MYSQL报错 我一开始是在.pro文件中加上了 QTsql QTmysq…

【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(5月31日论文合集)

文章目录 一、检测相关(10篇)1.1 Table Detection for Visually Rich Document Images1.2 DENTEX: An Abnormal Tooth Detection with Dental Enumeration and Diagnosis Benchmark for Panoramic X-rays1.3 TrueDeep: A systematic approach of crack detection with less dat…

C++ STL源码下载及目录结构

掌握一定的c基础&#xff0c;想更深入的了解STL源码实现的读者&#xff0c;可以参照本文下载源码阅读 1、源码下载 ​ SGI STL版本&#xff08;侯捷老师推荐&#xff09;&#xff1a;https://github.com/dongyusheng/csdn-code/tree/master/STLgcc STL&#xff1a;GitHub - gc…

使用 Docker 部署 Jenkins 代理(主从)控制服务器

自动化是 DevOps 的核心。各种自动化工具和技术真正实现了持续集成和持续交付的概念。这些工具多年来发展迅速&#xff0c;但似乎永远存在的一个名字是Jenkins。 我们不会在这篇文章中讨论 CI-CD 的介绍性概念&#xff0c;也不会浪费时间展示 Jenkins 安装步骤。如果您是 Jenk…

Go1.21 速览:骚操作 panic(nil) 将成为历史!以后别这么干了。。。

大家好&#xff0c;我是煎鱼。 在 Go 语言中&#xff0c;返回错误、抛出异常一直是大家比较关注的话题。在抛出异常上&#xff0c;我们一般都是这么用的&#xff1a; func mayPanic() {panic("脑子进煎鱼了") }func main() {defer func() {if r : recover(); r ! nil…

Vagrant编排虚拟机安装与配置

1.安装VirtualBox与Vagrant VirtualBox与Vagrant是支持不通过操作系统的&#xff1b;根据具体操作系统下载对应版本即可。(这里使用windows操作系统搭建) VirtualBox https://www.virtualbox.org/wiki/Downloads Vagrant https://developer.hashicorp.com/vagrant/downloads Va…

设计模式之~状态模式

状态模式&#xff08;State&#xff09;&#xff0c;当一个对象的内部状态改变时允许改变其行为&#xff0c;这个对象看起来像是改变了其类。 能够让程序根据不同的外部情况来做出不同的响应&#xff0c;最直接的方法就是在程序中将这些 可能发生的外部情况全部考虑到&#xff…

基于html+css的图展示102

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

应用运维的三个项目

应用运维 目录概述需求&#xff1a; 设计思路实现思路分析1.开发和运维2.比重3.历史项目4.工作内容5.历程 参考资料和推荐阅读 Survive by day and develop by night. talk for import biz , show your perfect code,full busy&#xff0c;skip hardness,make a better result,…

程序员的新出路:维护老项目?

1 张大胖刚进入公司&#xff0c;遇到了一个神奇的同事&#xff1a;何小痩。 别人工作都很忙&#xff0c; 何小痩工作似乎特别轻松&#xff0c;从来不加班&#xff0c;到点儿就回家。 张大胖向别人一打听&#xff0c;原来何小痩一直在维护一个老项目&#xff0c;维护了5年了。 …

「小产品独立变现实战训练营1期」门票限时优惠

大家好&#xff0c;我是凯凯刘&#xff0c;一名程序员&#xff0c;一直在做小产品的开发变现&#xff0c;目标就是让小产品的变现更简单。【小产品独立变现实战训练营1期】这个课程主要是围绕着如何开发出一个赚钱小产品这个主题。来跟大家一起从0开始实战&#xff0c;一步步跟…

为什么对象存储深度归档价格低?

AWS&#xff08;亚马逊云服务&#xff09;对象存储S3&#xff08;Simple Storage Service&#xff09;有以下四种不同的存储类型&#xff1a; S3 标准存储&#xff1a; 这是最常用的S3存储类型之一&#xff0c;它保证了高持久性&#xff0c;并提供 99.999999999% 的数据耐久性…

chatgpt赋能python:Python人脸识别:从入门到工程实践

Python人脸识别:从入门到工程实践 介绍 近年来&#xff0c;人脸识别技术越来越成熟&#xff0c;广泛应用于各行各业&#xff0c;如社交媒体、安防、金融等领域。Python人脸识别作为一种基于机器学习的技术&#xff0c;可以通过训练模型从图像中自动识别出人脸&#xff0c;并进…

致敬六一,用外观模式实现一个儿童乐园畅玩平台

一、概述 外观模式&#xff08;Facade Pattern&#xff09;是一种结构型设计模式&#xff0c;它为多个子系统中的操作提供一个统一的高层接口&#xff0c;用于访问复杂子系统的功能。其核心思想是通过一个外观类将子系统的复杂操作进行封装&#xff0c;客户端只需与外观类进行…

IO 多路复用是什么意思?Redis中的IO又是什么?

点击上方关注 “终端研发部” 设为“星标”&#xff0c;和你一起掌握更多数据库知识 本文首发于我的知乎&#xff1a;https://zhuanlan.zhihu.com/p/632776455 当你打开电脑&#xff0c;任何时候都在进行着IO的操作&#xff01; 比如一次 API 接口调用、向磁盘写入日志信息&…