我所理解的多线程

第一次写,可能比较混乱,个人理解也有限,欢迎喷

1.    什么是多线程?

1.1 执行流

关于操作系统的进程的概念我就不说了,这个应该都知道,线程是最基本的执行单元。多线程是在多任务操作系统之后带来的一个伪并行的机制。因为就单核cpu来说是没有真正的并行的,只是多道程序设计的方式,使得处理器在所有任务之间来回切换,给用户一种并行的感觉。真正的并行是多核处理器才能实现的,这种伪并行带来的好处是降低了任务的平均响应时间,但是虽然降低了平均响应时间,却带来了线程切换对CPU的损耗。所以总的来说是对任务的执行的总时间延长了。这样的做法使得紧急任务得意快速的被响应。

对于处理器来说,只知道加电后按照程序计数器中的地址不断执行下去,在不断执行的过程中,我们把程序计数器中的下一条指令地址所组成的执行轨迹称为程序的控制执行流。

执行流就是一段逻辑上独立的指令区域,是人为给处理器安排的处理单元,指令是具备能动行的而数据,因此只有指令才具有执行的能力,他相当于动作的发出这,由他知道cpu产生相对应的行为。

 

执行流对应与代码,大到可以是整个程序文件,即进程,小到可以是一个独立功能的代码快,即函数,线程的本质上就是函数。

执行流是独立的,他的独立性体现在每个执行流都有自己的栈,一套自己的寄存器映像和内存资源。就是所谓的上下文环境。要构建一个执行留就必须提供这一整套的资源。寄存器映像,栈,内存等。

1.2 中断处理程序

所谓的线程任务切换就是改变了处理器中程序计数器的指向。--这里还设计到一个中断的概念。

我们先说一下中断处理程序,CPU处理突发情况的技术。他能使CPU在运行过程中对外部时间发出的中断请求及时的进行处理。处理完成后又返回中断点,继续进行CPU原来的操作,中断根据中断源的不同分为外部中断和内部中断。

  外部中断: 比如硬件

内部中断:硬件程序的出错,奇偶校验码出错,突然断电,软件中断等。比如汇编的int 21中断等,中断向量表是一开始就存在内存地址0处的,中断码对应中断处理程序。的一个码表。

Os实现锁操作的就是开关中断或者一些os实现的同步原语操作比如CAS等。

 

2.Java如何实现锁机制

  2.1 这里说一下jvm的调度程序和锁机制。一开始我总是把线程调度程序和锁搞混乱。

线程调度程序是指jvm对线程执行的安排的算法。,Java使用的是抢占式线程调度。

2.11什么是抢占式线程调度

  就是按照线程的优先级,谁优先级高就先执行,但是jvm的这个优先级是动态的,如果一个线程一直在等待状态,这里大家应该都知道线程的五个状态。那么他的优先级会慢慢变高。

在线程执行的时候,如果遇到被同步代码指令标记的代码,怎么办呢,线程进入阻塞状态,然后去获取锁,怎么获取。线程有个队列Lock-free队列、使用CAS操作让线程去获取锁。然后线程进入等待状态,去执行同步代码块,执行完毕,释放锁。进入下一个循环。

锁机制就是在线程执行同步代码块的时候执行一个操作。获取了这个锁。这个锁是什么呢。是Java对象,我们都知道在jvm中,Java对象的结构里面有个对象头,里面由锁标志,让这个对象头和和线程关联,表示线程获取了锁

下图是我理解的jvm对象头和线程关系:

 

这个是转载https://blog.csdn.net/niuwei22007/article/details/51433669这个博客的:

下面首先介绍synchronized的实现:

synrhronized关键字简洁、清晰、语义明确,因此即使有了Lock接口,使用的还是非常广泛。其应用层的语义是可以把任何一个非null对象 作为"锁",当synchronized作用在方法上时,锁住的便是对象实例(this);当作用在静态方法时锁住的便是对象对应的Class实例,因为 Class数据存在于永久带,因此静态方法锁相当于该类的一个全局锁;当synchronized作用于某一个对象实例时,锁住的便是对应的代码块。在HotSpot JVM实现中,锁有个专门的名字:对象监视器。 

·        1.线程状态及状态转换

当多个线程同时请求某个对象监视器时,对象监视器会设置几种状态用来区分请求的线程:

Contention List:所有请求锁的线程将被首先放置到该竞争队列

Entry List:Contention List中那些有资格成为候选人的线程被移到Entry List

Wait Set:那些调用wait方法被阻塞的线程被放置到Wait Set

OnDeck:任何时刻最多只能有一个线程正在竞争锁,该线程称为OnDeck

Owner:获得锁的线程称为Owner

!Owner:释放锁的线程

下图反映了个状态转换关系:

新请求锁的线程将首先被加入到ConetentionList中,当某个拥有锁的线程(Owner状态)调用unlock之后,如果发现 EntryList为空则从ContentionList中移动线程到EntryList,下面说明下ContentionList和EntryList 的实现方式:

·        1.1ContentionList 虚拟队列

ContentionList并不是一个真正的Queue,而只是一个虚拟队列,原因在于ContentionList是由Node及其next指 针逻辑构成,并不存在一个Queue的数据结构。ContentionList是一个后进先出(LIFO)的队列,每次新加入Node时都会在队头进行, 通过CAS改变第一个节点的的指针为新增节点,同时设置新增节点的next指向后续节点,而取得操作则发生在队尾。显然,该结构其实是个Lock- Free的队列。

因为只有Owner线程才能从队尾取元素,也即线程出列操作无争用,当然也就避免了CAS的ABA问题。

 

lock的实现原理也类似,只不过是在os上对线程的控制,synchronize是在jvm上的控制。所用到的方法是类似的。

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值