线程

什么是线程

  • 在一个程序中,一个执行流就是一个线程,换句话说,线程是进程的内部控制序列。(在进程中,我们说一个运行中的程序就是一个进程)。
  • Linux下,线程被称为轻量级进程,由于在Linux下线程是由进程的pcb模拟实现,同一个进程中的线程共用进程的大部分资源。
  • 进程就是该进程下所有线程的一个统称(线程组),分配资源时是分配整个线程组(也就是进程)。进程就相当于一个工厂,线程就是工厂里的工人。
  • 进程是资源分配的基本单位,线程是CPU调度的基本单位。
    从内核看,线程与进程是一样的,都有自己的pcb,但是在同一进程中所有线程中pcb指向的是同一块虚拟地址空间。


进程与线程是包含关系,进程中最少含有一个线程。

线程资源的共享与独有

由于一个进程有多个线程,也就意味着一个进程有多个执行流,这些执行流同时访问同一块虚拟地址空间。是怎么做到不会出现调用栈混乱或者产生数据二义性呢?
线程并不是所有的资源都是共享的,其还有一部分资源是独有的。

共享资源

  • 代码段与数据段:线程是进程的一个执行流,共用程序的代码与数据。
  • 信号的处理方式:当线程遇到异常时,处理方式应该相同。
  • IO信息:
  • 工作路径:
  • 用户ID与用户组ID:
  • 优先级调度

独有资源

  • 线程ID:每个线程都有自己的pcb.
  • 调用栈:每个线程都有自己的一个调用栈,避免出现调用栈混乱。
  • 寄存器:由于每个线程都是一个独立的执行流。
  • 信号屏蔽字:屏蔽自己想屏蔽的信号。

线程的优点

  • 创建一个线程比创建一个进程的代价小。创建进程需要创建pcb,为pcb映射虚拟地址空间等。创建线程只需要创建一个pcb即可。
  • 同一个进程中的线程切换调度成本更低
  • 线程之间通信更加灵活方便,除过进程通信方式外,线程还可以通过全局变量,函数传参实现通信。
  • 线程所占的资源比进程小。

多线程与多进程

当只有一个进程时,想要执行增删改查,需要分4步顺序执行。

当有多个进程时,执行增删改查,就可以同步进行。

多线程执行时。

多线程处理思路:一个运行中的程序中,具有多个执行流,各自完成一个功能模块。

多线程与多进程的区别

线程的优点:

  • 创建销毁成本更低,创建线程的时候不需要为其分配虚拟地址空间。
  • 同一个进程的线程之间,切换调度成本更低。
  • 线程的通信方式更加灵活,在进程通信的基础上还可以通过函数传参与全局变量进行通信。
    进程的优点:
  • 健壮性更高,有的操作是对整个进程产生作用,例如:系统调用exit。

线程的创建

int pthread_create(pthread_t *tid,pthread_attr_t *attr,void* (*thread_routine)(void *arg),void *arg);
tid:输出型参数,用于向用户返回线程id
attr:设置线程属性,同常情况下NULL
thread_routine:线程的入口函数
arg:通过线程入口函数的参数传递给线程的数据
返回值:成功返回0,失败返回非0值

ps -L:查看轻量级进程信息。

LWP:轻量级进程的pid,实际就是pcb的pid。
在外面看到的进程id实际上就是tgid(线程组Id),线程组id等于进程中主线程的轻量级id

创建线程时,会在进程的虚拟地址空间中开辟一块相对独立的空间作为线程的地址空间,这个空间内包含用户对线程的描述,实现对线程的操作,创建成功后,会将这块空间返回给用户。用户就可以通过该内存首地址对线程进行操作,因此返回的线程地址空间的首地址就是线程的操作句柄,也就是pthread_create函数的tid。
线程地址空间是进程地址空间中的一部分

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>void *thread_func(void *arg)
{           printf("这个线程Id:%p\n",pthread_self());return NULL;
}          int main()
{     pthread_t tid;char *buf = "创建线程\n";int ret = pthread_create(&tid,NULL,thread_func,(void*)buf);if(ret!=0){printf("创建失败\n");return 0;} printf("普通线程Id:%p\n",tid);printf("主线程Id:%p\n",getpid());return 0;
}

注意:由于pthread_create接口是库函数,编译时需要加静态库
解决方法

线程终止

实质:退出一个线程

退出方式

  • 主动退出:线程入口函数中的return。(main函数中的return是用于退出进程而不是线程)
    void pthread_exit(void *retval);退出调用线程;retval:退出返回值。
  • 被动退出:
    int pthreadd_cancel(pthread_t thread);取消一个线程,thread:要取消线程的id

在主线程调用pthread_exit函数,可以退出主线程,但是不会退出进程,进程退出是当进程中的所有线程都退出后,进程才会退出。

线程等待

等待一个指定线程退出,获取这个退出线程的返回值,并且允许操作系统回收该线程所占的资源。
但是,不是所有的线程都需要被等待。
线程有一个属性默认值为:joinable,处于joinable属性的线程,退出后不会自动释放资源,需要其他线程进程等待处理。

本质
获取线程退出后的资源,释放该资源。

如何等待处理:

int pthread_join(pthread_t tid,void **retval);
tid:用于指定要等待的线程
retval:输出型参数,返回线程退出的返回值

pthread_join函数等待一个指定线程退出,若指定线程没有退出,则会一直等待。(阻塞函数)

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>void *Join_func(void *arg)
{printf("Normal thrread will eixt\n");sleep(5);char *buf = "Normal thread eixt\n";return buf;
}int main()
{pthread_t tid;int ret = pthread_create(&tid,NULL,Join_func,NULL);if(ret!=0){printf("thread create failed\n");return -1;}printf("Main thread waiting Normal thread to eixt\n");char *retval = NULL;pthread_join(tid,(void**)&retval);printf("retval:%s\n",retval);return 0;
}

线程分离

产生原因
由于处于joinable属性的线程退出后不会自动释放资源,所以需要线程等待,但是在线程等待中,会需要等待线程退出的返回值,再等待线程退出时需要耗费别的线程,当不想耗费别的资源时,就需要进行线程分离。

本质
设置线程属性,将joinable设置为detach,处于detach属性的线程退出后,会自动释放资源,这种线程不需要被等待。

如何分离一个线程

int pthread_detach(pthread_t tid);//分离一个指定线程,设置该线程的属性为detach
tid:用于指定线程

该函数为一个非阻塞函数,分离一个线程本质就是设置一个线程属性,所以在任意地方都可以调用该库函数

void detach_fun(void *arg)
{pthread_detach(pthread_self());//分离自己
}

线程ID

每个线程都有唯一的标识符,称为线程ID,该ID回返回给调用者。

  • 查看进行ID
    Pthread_self(void)该函数的返回值为Pthread_t类型,我们可以根据该函数的返回值,获取到线程的ID。
  • 判断线程ID是不是相等
    Pthread_equal(pthread_t p1,pthread_t p2);p1与p2相等,则返回非0,相等则返回0值。

Linux---多线程相关推荐

  1. Linux多线程的同步------读写锁

    前面介绍过Linux多线程同步的另外两个方法------互斥锁和信号量 Linux多线程的同步-----信号量和互斥锁_神厨小福贵!的博客-CSDN博客 下面来看一下读写锁: 读写锁和互斥锁都带有一个 ...

  2. Linux多线程的同步-----信号量和互斥锁

    前面两篇给基本概念讲过了,大家有兴趣的可以去看一下: Linux多线程_神厨小福贵!的博客-CSDN博客进程和线程的区别有哪些呢?进程是资源分配的最小单位,线程是CPU调度的最小单位进程有自己的独立地 ...

  3. Linux 多线程应用中编写安全的信号处理函数

    2019独角兽企业重金招聘Python工程师标准>>> Linux 多线程应用中编写安全的信号处理函数 在 开发多线程应用时,开发人员一般都会考虑线程安全,会使用 pthread_m ...

  4. linux 内核信号量与用户态信号量(system v,信号量在Linux多线程机制中的应用

    [摘 要]本文以信号量原理为基础,重点阐述信号量在Linux多线程同步机制中的实现特色. [关键词]信号量:Linux:多线程:同步 1 信号量 1965年E. W. Dijkstra首次提出信号量的 ...

  5. 新书预告:《Linux 多线程服务端编程——使用 muduo C++ 网络库》

    看完了 W. Richard Stevens 的传世经典<UNIX 网络编程>, 能照着例子用 Sockets API 编写 echo 服务, 却仍然对稍微复杂一点的网络编程任务感到无从下 ...

  6. linux多线程编写哲学家,Linux系统编程(三) ------ 多线程编程

    一.线程的创建和调度 1.线程是程序执行的某一条指令流的映像. 为了进一步减少处理机制的空转时间,支持多处理器及减少上下文切换开销,进程在演化中出现了另一个概念--线程.它是进程内独立的一条运行路线, ...

  7. linux多线程信号总结

    linux多线程信号总结-businiaowyf-ChinaUnix博客 linux 多线程信号处理总结 - CobbLiu - 博客园

  8. linux多线程求和_linux 多线程信号处理总结

    linux 多线程信号总结(一) 1. 在多线程环境下,产生的信号是传递给整个进程的,一般而言,所有线程都有机会收到这个信号,进程在收到信号的的线程上下文执行信号处理函数,具体是哪个线程执行的难以获知 ...

  9. Linux多线程——使用信号量同步线程

    http://blog.csdn.net/ljianhui/article/details/10813469/ 信号量.同步这些名词在进程间通信时就已经说过,在这里它们的意思是相同的,只不过是同步的对 ...

  10. Linux多线程——使用互斥量同步线程

    前文再续,书接上一回,在上一篇文章:Linux多线程--使用信号量同步线程中,我们留下了一个如何使用互斥量来进行线程同步的问题,本文将会给出互斥量的详细解说,并用一个互斥量解决上一篇文章中,要使用两个 ...

最新文章

  1. Python字符串类型及操作总结
  2. 意念控制成现实:不开口,不动手,“瘫着”就能打游戏
  3. python程序运行时间计时软件_python 计时程序运行时间
  4. 零元学Expression Blend 4 - Chapter 25 以Text相关功能就能简单做出具有设计感的登入画面...
  5. KEIL5 编译器导致的程序异常
  6. mysql 主从_搭建mysql主从并编写监控主从状态脚本
  7. 从奥巴马假视频到ZAO,换脸和人脸检测技术发生了什么?
  8. VS调试时断点无法进入或命中的原因及解决方法(PDB引发的)
  9. Android 代码动态生成ProgressBar
  10. 王思聪也救不了熊猫直播了?
  11. 可替代的C语言开发环境
  12. Python+Selenium ----unittest单元测试框架
  13. 6西格玛管理法和ISO9000标准(摘录)
  14. 凤凰系统(Phoenix OS)PC版安装,电脑上体验功能丰富的安卓系统
  15. 介绍几款高级DAC解码芯片(整编)
  16. iframe是什么?iframe用法详解。
  17. 谷歌浏览器显示一直加载的解决方法
  18. 电脑故障恢复控制台命令
  19. webpack 5高级配置优化
  20. [英语阅读]意环保者塑“老贝”冰雕督促环保

热门文章

  1. Kafka监控:Kafka-Manager
  2. C++程序设计:原理与实践(进阶篇)15.6 实例:一个简单的文本编辑器
  3. C#中的程序集和命名空间
  4. jmeter 及测试
  5. AndroidUI 布局动画-为布局添加动画
  6. java中IO写文件工具类
  7. ZOJ 3490 String Successor
  8. PowerDesigner物理模型用法总结
  9. 满分的项目经理,个人觉得很有道理,所以[转载]
  10. python读取超大文件-强悍的Python读取大文件的解决方案