欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  Java

java学习:什么是线程?最详细的解释

程序员文章站 2022-03-10 22:28:09
...
什么是线程:有时也被成为轻量级进程,是程序执行流的最小单元。

一个标准的线程是由线程ID,当前指令指针(PC)、寄存器集合和堆栈组成。

一个进程是由一个到多个线程组成,各个线程之间共享程序的内存空间(包括代码段,数据段的堆等)及一些进程级的资源(如打开文件和信号)

多个线程可以互不干扰的并发执行,并共享进程的全局变量和堆的数据;

线程的访问权限

线程的访问权限非常*,可以访问进程内存里的所有数据;

java学习:什么是线程?最详细的解释

线程调度与优先级

单处理器对应多线程:操作系统让这些多线程轮流执行,每次仅执行一小段时间(通常是几十秒),这样每个线程“看起来”就像是在同时执行;这样的一个处理器上不断切换线程的操作成为“线程调度”

线程调度中的三种状态:

1):运行,此时线程正在运行

2):就绪,此时线程可以立即运行,但CPU已被占用

3):等待,此时线程正在等待某一事件发生,无法执行

每当一个程序离开运行状态,调度系统就会选择一个就绪的线程运行;一个在等待状态的线程事件发生以后进入就绪状态。

java学习:什么是线程?最详细的解释

在优先级调度的情况下,线程优先级的改变一般有三种方式:

用户指定优先级;

根据进入等待状态的频繁程度提升或降低优先级;

长时间得不到执行而被提升优先级;

Linux的多线程

在Linux下,可以用以下三个方法创建一个新的任务:

(1)fork:复制当前进程

(2)exec:使用新的可执行映像覆盖当前可执行映像

(3)clone:创建子进程,并从指定位置开始执行;

fork:

pid_t pid;

if(pid==fork()){…}

在fork调用以后,新的任务启动并和本任务一起从fork函数返回,但不同的是本任务的fork将返回新任务的pid,而新任务的fork将返回0;

fork产生新任务的速度非常快,因为fork不复制原任务的内存空间,而是和原任务一起共享一个写时拷贝的内存空间;

所谓写时拷贝:指的是两个任务可以同时*地读取内存,但任意一个任务试图对内存进行修改时,内存就会复制一份提供给修改方单独使用,以免影响到其他的任务使用;

java学习:什么是线程?最详细的解释

fork只能够产生本任务的镜像,因此必须使用exec配合才能启动别的新任务,exec可以用新的可执行映像替代当前的可执行映像,因此在fork产生了一个新任务之后,新任务可以调用exec来执行新的可执行文件;

头文件都定义在pthread.h中

创建一个线程:#include<pthread.h>

int pthread_create (pthread_t *thread,const pthread_attr_t* attr,void*(*start_routine)(void*),void*arg)

thread参数是新线程的标识符,后续的pthread_*函数通过它来引用新线程;

attr参数用于设置新线程的属性,给它传递NULL表示使用默认线程属性;

Start_routine 和arg参数分别制定新线程将运行的函数及参数;

pthread_create成功时返回0,失败时返回错误码;

结束一个线程:void pthread_exit(void *retval)

函数通过retval参数向线程的回收者传递其退出信息;

线程安全:

多线程程序处于一个多变的环境当中,可访问的全局变量和堆数据都可能随时被其他的线程改变;

手段:同步与锁

原子的:单指令操作称为原子的,无论如何,单条指令的执行是不会被打断的;

为了避免多个线程同时读写一个数据而产生不可预料的后果,我们要将各个线程对同一个数据的访问同步(所谓同步,就是在一个线程访问数据未结束时,其他线程不得对同一个数据进行访问),因此,对数据的访问被原子化;

同步的常见方法:(信号量、互斥量、临界区,读写锁、条件变量)

锁:每一个线程在访问数据或资源时首先试图获取锁,并在访问结束后释放锁;

信号量:线程访问资源的时候首先获取信号量;

操作如下:

(1)将信号量的值减1;

(2)如果信号量的值小于0,则进入等待状态;否则继续执行;

访问完资源之后,线程释放信号量;

(3)将信号量的值加1;

(4)如果信号量的值小于1,唤醒一个等待中的线程;

互斥量&&信号量

同:资源仅同时允许一个线程访问;

异:信号量在整个系统中,可以被任意线程获取并释放,也就是说,同一个信号量可以被系统中的一个线程获取后,另一个线程释放;

而互斥量要求哪个线程获取了互斥量,哪个线程就要负责释放这个锁,其他线程越俎代庖去释放互斥量是无效的;

临界区:是比互斥量更加严格的同步手段

把临界区的锁的获取称为进入临界区;

而把锁的释放称为离开临界区。

区别(与信号量和互斥量)

互斥量和信号量在系统的任何进程里都是可见的;

也就是说一个进程创建了一个互斥量或信号量,另一个进程试图去获取该锁是合法的;

临界区的作用范围仅限于本进程,其他的进程无法获取该锁

读写锁:

两种方式:共享的 独占的

java学习:什么是线程?最详细的解释

当锁出于*状态时,试图以任何一种方式获取锁都能成功,并将锁置于对应的状态;(如上图)

条件变量:作为同步的一种手段,作用类似于一个栅栏;

对于条件变量,线程有两种操作:

(1)首先线程可以等待条件变量,一个条件变量可以被多个线程等待;

(2)线程可以唤醒条件变量,此时某个或所有等待此条件变量的线程都会被唤醒并继续支持;

(也就是说,使用条件变量可以让许多现车鞥一起等待某个事件的发生,当事件发生时,所有线程可以一起恢复执行)。

相关文章:

什么是进程(process)?什么是线程?

基于java学习中多线程的实现方法

以上就是java学习:什么是线程?最详细的解释的详细内容,更多请关注其它相关文章!

相关标签: java 线程