认识线程

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

​ 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 cond2.条件变量初始化:pthread_cond_init(&cond,&attr)3.用户在判断条件不满足的情况下提供等待功能 pthread_cond_wait(&cond,&mutex);
为什么条件变量要与互斥锁一起使用:线程什么时候等待,需要一个判断条件;这个判断条件也是临界资源(等待了之后,其他线程需要促使这个条件满足(修改临界资源));因此这个临界资源的操作就需要受保护(默认使用互斥锁实现保护)4..用户在促使条件满足条件后,唤醒等待 pthread_cond_signal (唤醒至少一个线程)
pthread_cond_broadcast(唤醒所有线程)

【Linux】线程概念与线程控制相关推荐

  1. Linux 多线程(一)线程概念:线程概念、线程与进程、线程间的独有与共享、多线程与多进程、线程控制

    线程概念 线程与进程 线程间的独有与共享 多线程与多进程 线程控制 线程概念 什么是线程 线程是进程中的一条执行流,执行程序中的某部分代码.linux下没有具体实现的线程,只有库函数用pcb来实现的线 ...

  2. [Linux]线程概念_线程控制(线程与进程的区别与联系 | 线程创建 | 线程等待 | 线程终止 | 线程分离 | LWP)

    文章目录 线程概念 进程和线程的关系 线程的优点 线程的缺点 线程控制 Linux线程和接口关系的认识 线程创建 线程ID及进程地址空间布局 线程等待 线程终止 线程终止状态 线程分离 LWP和pth ...

  3. Linux多线程---线程概念和线程控制

    线程概念 什么是线程? CPU视角: 与进程的关系: Linux下线程概念 那么CPU能分辨task_struct是进程和线程吗? 理解页表 为何以多级页表实现? 多级页表是如何实现的? 多级页表的优 ...

  4. 【Linux 内核】进程管理 ( 内核线程概念 | 内核线程、普通进程、用户线程 | 内核线程与普通进程区别 | 内核线程主要用途 | 内核线程创建函数 kernel_thread 源码 )

    文章目录 一.内核线程概念 二.内核线程.普通进程.用户线程 三.内核线程.普通进程区别 四.内核线程主要用途 五.内核线程创建函数 kernel_thread 源码 一.内核线程概念 直接 由 Li ...

  5. 1线程概念:线程和进程之间的关系,线程间可共享资源,线程间非共享资源,线程的优缺点

     1线程概念 1.1什么是线程 1.1.2线程和进程的关系 1.轻量级进程(light-weightprocess),也有PCB,创建线程使用底层函数和进程一样,都是clone. 2.从内核里看进 ...

  6. java基础巩固-宇宙第一AiYWM:为了维持生计,多高(多线程与高并发)_Part1~整起(线程与进程篇:线程概念、线程状态、线程死锁)

    这个题目我感觉很多大哥大姐和我一样,虽然夹在众位大哥大姐中跟着一块喊着"多线程与高并发"的口号,但是这里面其实包含的东西并不像名字里面这么少.现在就开始咱们的旅程吧. 特此感谢,低 ...

  7. java线程通信概念_java基础线程总结(线程概念、线程创建方式、线程间通信、线程重要方法)...

    基础篇之<线程> @author :kern ---------------------------------------------------------------- 一:进程:是 ...

  8. 【Linux入门】多线程(线程概念、生产者消费者模型、消息队列、线程池)万字解说

    目录 1️⃣线程概念 什么是线程 线程的优点 线程的缺点 线程异常 线程异常 Linux进程VS线程 2️⃣线程控制 创建线程 获取线程的id 线程终止 等待线程 线程分离 3️⃣线程互斥 进程线程间 ...

  9. 多线程概念,线程控制

    文章目录 多线程 线程概念 多任务处理: 多线程/多进程进行多任务处理的优缺点分析 多线程的优点 多进程的优点 共同的优点 线程控制 线程的创建 线程的终止 线程的等待 线程的分离 多线程 线程概念 ...

最新文章

  1. OSPF高级设置实现全网互通
  2. 模拟video播放器
  3. Rackspace进中国,坚决“不掉价”
  4. C# Owin 创建与测试自己的中间件Middleware
  5. 关于COUNT STOPKEY的工作机制
  6. wifi信号增强android,WiFi信号增强大师APP
  7. HALCON示例程序circles.hdev边界轮廓的圆形拟合
  8. 使用Twitter Bootstrap,WebSocket,Akka和OpenLayers玩(2.0)
  9. HTML5 实现离线数据缓存
  10. Android4开发入门经典 之 第七部分:数据存储
  11. VMware vSphere之vCenter安装
  12. 自定义一个ImageSwitcher
  13. MySQL------存储过程的使用
  14. 国内太极AI智能交易系统
  15. Linux I2C驱动
  16. 记一次微信小程序云函数操作Mysql数据库
  17. c#十二星座速配系统_不同的调是否具有独立色彩?作曲时如何选择用什么调?...
  18. saber软件安装常见问题
  19. ArrayMap源码注释
  20. 证明SST=SSR+SSE

热门文章

  1. 1999-2018年地级市年末实有耕地面积、人均耕地面积、行政区域土地面积、人口密度等
  2. Android开发蓝牙与ble设备的通讯
  3. 2023软考中级职称电子商务设计师之路一
  4. 511遇见易语言循环遍历删除数组中重复成员方法
  5. Cisco Packet Tracert 邮件服务器配置
  6. 『论文阅读』SIF:一种简单却难以打败的句子嵌入方法
  7. 正交表 软件测试作业,软件测试单元3 黑盒测试
  8. Aseprite-绘制杯子、剑、骷髅头和人脸
  9. 直接按开关机键重启服务器
  10. 程序员面试必备的5个问题