【Linux】线程概念与线程控制

news2024/12/24 21:53:28

认识线程

线程是一个执行流(运行代码,处理数据)

​ 1.操作系统使用pcb来描述一个程序的运行-------pcb就是进程

​ 2.linux下通过pcb模拟实现线程,因此linux下的线程是一个轻量级进程
​ 3.这个轻量级进程因为公用大部分进程资源;相较于传统进程更加轻量化
进程是资源分配的基本单位----因为程序运行时资源分配给整个线程组(线程是cpu调度的基本单位-----因为linux pcb是线程)
线程之间资源的独有与共享
​ 独有:寄存器(自己的上下文数据[上文:处理过的数据;正文:正在处理的数据;下文:即将处理的数据]), 信号屏蔽字(那个线程拿到时间片就会处理信号,若不想让该线程处理某信号,则在该线程信号屏蔽),errno(每个线程都有自己的errno,防止errno改正后,统一被修改),线程ID,调度优先级

​ 共享:共享虚拟地址空间(共享代码段和数据段),文件描述符表(一个线程打开文件获取文件描述符可以直接传给另一个线程,另一个线程直接进行文件操作),当前工作路径信号处理方式(信号处理方式一致,但是具体哪一个进程去处理是不一定的),用户id/组id

多进程与多线程的优缺点分析

多线程处理任务的优点:

  • 线程间通信特别方便,除了进程间的通信方式,还可以通过全局变量/传参(共享资源)
  • 创建和销毁一个线程的成本相比于进程要更低
  • 线程间调度相较于进程要更低

多线程处理任务的缺点:

  • 线程之间缺乏访问控制,有些系统调用/异常针对的是整个进程;稳定性相比于进程更低。场景:比如创建shell这种对主程序稳定安全性要求较高的程序,就需要用多进程,让子程序来背锅

线程控制

线程创建/线程终止/线程等待/线程分离
由于linux下操作系统并没有提供线程的控制系统调用接口,封装了一个线程控制接口库。使用库函数实现创建的线程我们称之为用户态线程,这个用户态线程在内核中使用一个轻量级进程实现调度。
POSIX线程库

  • 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”打头的
  • 要使用这些库函数,要通过引入头文件<pthread.h>
  • 链接这些线程函数库时,要使用编译器命令的"-lpthread"选项
    linux下的线程:用户态线程+轻量级进程

线程创建

//int pthread_create(pthread_t * thread,const pthread_attr_t *attr,
//void* (start_routine)(void*) ,void* args);
//thread:用来获取线程id
//attr:用来设置进程属性以及栈的大小,通常置为NULL;
//start_routine:线程的入口函数
//arg:传递给进程入口函数的参数
//返回值:0表示成功,!0表示不成功
#include <stdio.h>
    2 #include <unistd.h>
    3 #include <pthread.h>
    4 
    5 //线程创建,体会每个线程都是执行流
    6 void* thr_entry(void* arg)
    7 {
    8   while(1)
    9   {
   10     printf("i am common thread-----%s\n",(char*)arg);
   11     sleep(1);                                                                                                     
   12   }
   13   return NULL;
   14 }
   15 
   16 int main()
   17 {
   18   //int pthread_create(pthread_t *thread,const pthread_attr_t *attr,
   19   //void* (*start_routine)(void*),void* args)
   20   pthread_t tid;
W> 21   char* param = "this is input param";
   22   int ret = pthread_create(&tid,NULL,thr_entry,(void*)param);
   23   if(ret != 0)
24   {
   25     printf("pthread create error\n");
   26     return -1;
   27   }
W> 28   printf("tid:%p\n",tid);
   29   while(1)
   30   {
   31     printf("i am main thread-----\n");
   32     sleep(1);
   33   }
   34   return 0;
   35 }                                                                                                                 

在这里插入图片描述
ps -efL //可以查看轻量级进程
线程中的id讨论:
​tid : 线程地址空间首地址,方便用户操作线程
​pcd->pid 轻量级进程id(LWP)
pcb->tgid 进程(线程组)id,默认等于首线程地址id

线程终止

//return   不能在main函数中return(退出的是进程-----导致所有线程退出)
//void pthread_exit(void * retval);        退出线程自身,谁调用谁退出//retval:线程退出的返回值
//int pthread_cancel(pthread_t thread);取消其他线程,让其他线程退出//thread:要取消的线程ID
//线程退出后,默认不会自动释放资源,(保存自己的退出结果在线程独有的地址空间中),会造成资源泄露
//主线程退出,其他线程依然可以正常运行
    1 #include <stdio.h>                                                                                                
    2 #include <unistd.h>
    3 #include <pthread.h>
    4  
    5 void* thr_entry(void* arg)
    6 {
    7   //pthread_exit(NULL)退出当前线程
    8   pthread_cancel((pthread_t) arg);          
    9   pthread_t ctid;
   10   ctid = pthread_self();              
   11   while(1){                                                 
W> 12     printf("i am common pthread--------%p\n",ctid);
   13     sleep(1);
   14   }                                  
   15   return NULL;
   16 }  
   17 int main()               
   18 {                                    
   19   pthread_t mtid;
   20   mtid = pthread_self();//获取本线程的ip地址
   21   pthread_t tid;
W> 22   char* param = "this is input param";
   23   int ret = pthread_create(&tid,NULL,thr_entry,(void*)mtid);
      24   if(ret != 0)                                     
   25   {          
   26     printf("pthread create error\n");
   27     return -1;
   28   }
W> 29   printf("tid:%p\n",tid);
   30   //pthread_cancle(tid); 取消普通线程
   31   while(1){      
   32     printf("i am main thread-------\n");    
   33     sleep(1);   
   34   }                                   
   35 }                                                                                                                 

在这里插入图片描述

线程等待

概念:等待指定线程退出,获取这个线程的退出返回值,并回收这个线程的资源。
​ 一个线程有默认属性:joinable;处于joinable属性的线程退出后为了保存返回值,因此不会自动释放资源
​ 如果不进行等待会造成内存泄漏(一个线程只有处于joinable状态的时候,才需要被等待)
​ pthread_join(pthread_t tid,void **retval);

线程分离

是将线程的joinable属性修改为detach属性
​ 线程若处于detach属性,则线程退出后将自动回收资源;并且这个线程不需要等待,因为线程返回值占用的空间已经被回收。
pthread_detach(pthread_t tid)
线程分离的适用场景:
一进入自己的线程就线程等待:pthread_detach(pthread_self());

#include <stdio.h>
    2 #include <unistd.h>
    3 #include <errno.h>
    4 #include <pthread.h>
    5 
    6 //线程等待
    7 void* thr_entry(void* arg)
    8 {
    9   pthread_detach(pthread_self());
   10   sleep(3);
W> 11   char* ptr = "hello";
   12   pthread_exit(ptr);                                                                                              
   13   pthread_cancel((pthread_t)arg);
   14   while(1)
   15   {
   16     printf("i am common thread----%s\n",(char*)arg);
   17     sleep(1);
   18   }
   19 }
   20 
   21 int main()
   22 {
   23   pthread_t mtid;
#include <stdio.h>
    2 #include <unistd.h>
    3 #include <errno.h>
    4 #include <pthread.h>
    5 
    6 //线程等待
    7 void* thr_entry(void* arg)
    8 {
    9   pthread_detach(pthread_self());
   10   sleep(3);
W> 11   char* ptr = "hello";
   12   pthread_exit(ptr);                                                                                              
   13   pthread_cancel((pthread_t)arg);
   14   while(1)
   15   {
   16     printf("i am common thread----%s\n",(char*)arg);
   17     sleep(1);
   18   }
   19 }
   20 
   21 int main()
   22 {
   23   pthread_t mtid;

在这里插入图片描述

线程安全

多个线程同时对临界资源进行访问而不会造成数据二异性

如何实现线程安全:

同步:时序合理性

互斥:对临界资源同一时间的访问唯一性
线程间互斥实现:互斥锁

  • 1.定义互斥锁变量
pthread_mutex_t
  • 2.对互斥锁变量进行初始化
pthread_mutex_init(mutex,attr);//mutex : 互斥锁变量//attr: 初始化互斥锁属性---通常置NULL
  • 3.对临界资源操作之前先加锁 [在对临界资源操作之前加锁],若可以加锁则直接修改计数,函数返回;否则挂起等待
pthread_mutex_lock(&mutex);
pthread_mutex_trylock   //  pthread_mutex_timedlock
  • 4.对临界资源操作完毕后进行解锁 [在对临界资源操作之后立即解锁,线程退出之前也要解锁]
	pthread_mutex_unlock(&mutex)

5.销毁互斥锁

	pthread_mutex_destory(&mutex)

死锁:多个线程对锁资源进行竞争访问,但是因为推进顺序不当导致相互等待,以至于程序无法往下运行
死锁产生的四个必要条件
1.互斥条件:一个锁只有一个线程可以获取

2.不可剥夺条件:我上的锁别人不可以解

3.请求与保持条件:拿着A锁去请求B锁,若获取不到B锁,也不会释放A锁。

4.环路等待条件:A拿着A锁去请求B锁,B拿着B锁去请求A锁。

死锁预防:避免这4个必要条件
死锁避免:死锁检测算法,银行家算法

线程同步

线程同步的实现:等待+唤醒
操作不满足等待条件,别人促使等待条件满足后唤醒等待

条件变量
条件变量实现同步:用户在对临界资源访问之前,先判断是否能够操作,若可以,线程直接操作;若不能,条件变量提供等待条件,让pcb在等待队列上。其他线程促使操作条件满足,唤醒条件变量等待队列上的线程。

1.定义条件变量:pthread_cond_t cond

2.条件变量初始化:pthread_cond_init(&cond,&attr)

3.用户在判断条件不满足的情况下提供等待功能 pthread_cond_wait(&cond,&mutex);
为什么条件变量要与互斥锁一起使用:线程什么时候等待,需要一个判断条件;这个判断条件也是临界资源(等待了之后,其他线程需要促使这个条件满足(修改临界资源));因此这个临界资源的操作就需要受保护(默认使用互斥锁实现保护)

4..用户在促使条件满足条件后,唤醒等待 pthread_cond_signal (唤醒至少一个线程) 	        
pthread_cond_broadcast(唤醒所有线程)

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

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

相关文章

Python编程 字典创建map与Zip

作者简介&#xff1a;一名在校计算机学生、每天分享Python的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 字典(dict) 字典创建(拓展) 拓展&#xff1a; 前言 本章将会扩展Python…

IP 地址详解(IPv4、IPv6)

文章目录1 概述2 IP 地址结构2.1 IPv4 地址结构2.2 IPv6 地址结构3 IP 地址管理3.1 地址分类策略&#xff1a;A、B、C、D、E 类3.2 无分类策略&#xff1a;CIDR3.3 地址分类策略 和 无分类策略 相结合1 概述 IP地址&#xff1a;Internet Protocol Address&#xff08;互联网协…

Flutter高仿微信-第25篇-服务条款

Flutter高仿微信系列共59篇&#xff0c;从Flutter客户端、Kotlin客户端、Web服务器、数据库表结构、Xmpp即时通讯服务器、视频通话服务器、腾讯云服务器全面讲解。 详情请查看 效果图&#xff1a; 实现代码&#xff1a; /*** Author : wangning* Email : maoning20080809163.…

基于JavaWeb的物流管理系统的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

电视机@2022:降价、焦虑与机遇

【潮汐商业评论/原创】 双十一期间&#xff0c;以前从不参与这类抢购的Gant也加入了这场“狂欢”。用他自己的话说&#xff1a;“生活压力好大啊&#xff0c;我不上班的时候就喜欢刷剧放松&#xff0c;所以就想趁着购物节挑台性价比高的电视&#xff0c;毕竟囊中羞涩嘛&#x…

端口映射与容器互联

1. 端口映射实现访问容器&#xff1a; 在启动容器的时候&#xff0c;如果不指定对应的参数&#xff0c;在容器外部是无法通过网络来访问容器内部的网络应用和服务的。 当容器中运行一些网络应用&#xff0c;要让外部访问这些应用时&#xff0c;可以通过-p或-P参数来指定饼口映…

总结了几个做用户体验设计的原则,分享给需要的朋友

近一年来&#xff0c;Figma它可以说是体验设计领域最受欢迎的工具。最近&#xff0c;我开始频繁地工作。Axure9.0和Figma切换使用&#xff0c;深刻感受到设计细节带来的体验差异化。今天&#xff0c;通过一些细节和亮点&#xff0c;总结了工具软件体验设计的几个原则。 ​一、效…

HTTP服务器

HTTP服务器 1. 项目背景和技术特点 实现目的 从移动端到浏览器&#xff0c;HTTP 协议无疑是打开互联网应用窗口的重要协议&#xff0c;其在网络应用层中的地位不可撼动&#xff0c;是能准确区分前后台的重要协议。 完善对HTTP协议的理论学习&#xff0c;从零开始完成WEB服务器…

万字string类总结

目录 一、string类的介绍 二、string类的常用接口 1、构造函数 2. string类对象的容量操作 3. string类对象的访问及遍历操作 4. string类对象的修改操作 &#xff08;重点&#xff09; 5. string类非成员函数 6. vs和g下string结构的说明 三、string类的模拟 1. 浅拷…

c++智能指针(raii)

目录 1.智能指针的作用 2.智能指针带来的问题与挑战 3.三种不同的智能指针 4.auto_ptr 5.unique_ptr 6.shared_ptr 7.weak_ptr&#xff1b;相互引用 8.总结 1.智能指针的作用 以c的异常处理为例看看throw catch用法。有时&#xff0c;一个用new开出的空间用完还没delete…

[附源码]java毕业设计壹家吃货店网站

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【C语言】学数据结构前必学的结构体struct详细

佛祖说&#xff0c;他可以满足程序猿一个愿望。程序猿许愿有生之年写出一个没有bug的程序&#xff0c;然后他得到了永生。 目录 1、结构体的声明与定义 1.1结构体是什么&#xff1f; 1.2为什么要有结构&#xff1f; 1.3结构体的声明 1.4结构体成员类型 1.5结构体变量定义…

由CPU高负载引发内核探索之旅

导语&#xff1a;STGW&#xff08;腾讯云CLB&#xff09;在腾讯云和自研业务中承担多种网络协议接入、请求加速、流量转发等功能&#xff0c;有着业务数量庞大、接入形式多样、流量规模巨大的特点&#xff0c;给产研团队带来了各种挑战&#xff0c;经常要深入剖析各种疑难杂症。…

Win7纯净版系统镜像64位介绍

Win7系统是一款非常经典的系统&#xff0c;这里想为大家介绍的是Win7纯净版系统镜像64位&#xff0c;主要特点就是非常稳定&#xff0c;运行流畅、占用CPU和内存都非常少。系统非常纯净&#xff0c;使用此系统&#xff0c;可让你的电脑焕然一新&#xff01; 一、系统稳定 1、采…

科普读书会丨《被讨厌的勇气》:愤怒不是目的,是一种工具

Hello&#xff0c; 这里是壹脑云读书圈&#xff0c;我是领读人小美~ 《被讨厌的勇气》读书会目前已经进行了两期&#xff0c;成员们也共同探讨了其中第一夜和第二夜的内容。每个人都有被情绪困扰的时候&#xff0c;而阿德勒心理学告诉我们&#xff0c;即使是负面情绪也不可怕…

WebRTC 服务器搭建篇

First off All 服务器环境&#xff1a;采用的阿里云国内服务器&#xff0c;系统&#xff1a; Ubuntu 16.04 64位 。 各个服务所需要的编译环境图&#xff1a; 各个服务器对应所需编译平台 1.第一步&#xff0c;先更新下命令行工具&#xff0c;工欲善其身必先利其器&#xff…

推荐一款图表功能强大的可视化报表工具

企业信息化建设&#xff0c;大量的数据需要经过分析才能挖掘价值。因此数据的价值越来越受到大家的重视&#xff0c;大数据分析工具逐渐成为企业运营必不可少的辅助工具。俗话说工人要想做好事&#xff0c;首先要磨利工具&#xff0c;拥有一个好用的大数据分析工具尤为重要&…

numpy生成0和1数组方法、从已有数组生成新数组方法、生成固定范围内数组、生成随机数组、绘制指定均值和标准差正态分布图、均匀分布图绘制

一、生成0和1数组 np.ones(shape, dtype)&#xff1a;shape为要生成的数组的维度&#xff0c;dtype为数组内元素类型np.ones_like(a, dtype)&#xff1a;生成与a同维度的数组np.zeros(shape, dtype)np.zeros_like(a, dtype) 代码如下 one np.ones([3,4]) one --------------…

机器学习——支持向量机与集成学习

支持向量机与集成学习 文章目录支持向量机与集成学习支持向量机的基本原理线性可分支持向量常用核函数集成学习概述集成学习的两种方式集成学习的基本类型弱学习其合成方式AdaBoost算法训练过程简例一类按监督学习方式对数据进行二元分类的广义线性分类器 文章目录支持向量机与…

免费不限时长的语音转文字软件——Word365

适用场景 想将语音转化成文字。 这里的语音可以是实时输入&#xff0c;也可以是已有音、视频转换成文字。 后者的操作比前者多一步操作。 1.实时语音转文字 可以直接打开Word365&#xff0c;【开始】选项卡中的【听写】功能。 打开前修改一下设置&#xff0c;语言可以根据需…