线程并发共享资源同步原理解析1

来源:互联网 发布:ubuntu cmd命令窗口 编辑:程序博客网 时间:2024/05/17 18:40

 存储访问的不一致原因:a、CPU访问存储的方式---多级存储;b、CPU执行指令的方式----乱序


 synchronized给出的答案是在软件层面依赖JVM,而Lock给出的方案是在硬件层面依赖特殊的cpu指令。

 新请求锁的线程将首先被加入到ContentionList中,当某个拥有锁的线程(Owner状态)调用unlock之后,如果发现EntryList为空则从

ContentList中移动线程到EntryList


 1、自旋锁:

ContentionList、entryList、waitset中的线程均处于阻塞状态,阻塞操作由操作系统完成,线程被阻塞后便进入内核调度状态,这个导致

系统在用户态和内核态之间来回切换,严重影响性能。线程在进入等待队列时首先进行自旋尝试获得锁,如果不成功在进入等待队列。

{
用户态和内核态:intel X86架构的CPU提供里四个特权级,linux使用0(最高)和3(最低)。

内核栈:Linux中每个进程又两个栈分别用于用户态和内核态的程序进行,其中的内核栈就是用于内核态的堆栈,它和进程的task_struct结构,更具体的是

是thread_info结构一起放在两个连续的页框大小的空间内。

用户态就是特权级为3的程序,内核态是特权级为0的程序

用户运行一个程序,该程序所创建的进程开始是运行在用户态的,如果要执行文件操作、网络数据发送等操作,必须通过write,send等系统调用,需要内核

代码完成,需要切换到ring0(内核态),完成后回到ring3(用户态)。

cpu处于用户态只能通过中断的方式进入内核态,处于内核态时可以随时切换到用户态。在内核态下,CPU可执行任何指令,在用户态下CPU只能执行非特权指令。

用户态切换到内核态的3种方式:a、系统调用 b、异常 c、外围设备中断。实际都是中断处理机制实现的。

结束线程三个方法:1、stop立即强制结束线程,即使在同步方法中,因此容易产生不完整的残废数据。

2、thread.interrupt();将线程中断标志位设为true,可以恢复或死亡。

如果一个线程处于了阻塞状态(如线程调用了thread.sleep、thread.join、thread.wait、1.5中的condition.await、以及可中断的通道上的 I/O 操作方法后可

进入阻塞状态),则线程在检查中断识别时,如果发现标志位true,则会在这些阻塞方法调用出抛出InterruptedException异常,并且在抛出异常后立即将线程的

中断标志位至为false。抛出异常为了线程从阻塞状态醒过来置为非中断状态,如果catch语句没有处理异常,则下一次循环中如果isInterrupted为false,线程继

续执行,可能你N次抛出异常也无法让线程终止。

3、在Thread对象中设置共享变量作为中断信号量,通过在run方法中不断检测该变量的值来决定是否结束。
}


synchronized的底层实现主要依靠lock-free的队列,借本思路是自旋后阻塞,竞争切换后继续竞争锁,稍微牺牲里公平性,但获得高吞吐量。

 

2、偏向锁:(无竞争)

现在几乎所有的锁都是可重入的,也即已经获得锁的线程可以多次锁住/解锁监视对象。每次加锁和解锁都会涉及一些CAS操作,该操作会延迟

本地调用,因此偏向锁是一旦线程第一次获得监视,之后让监视对象偏向这个线程之后可以多次调用避免CAS操作。意思就是添加变量,如果

发现为true则无需走各种解锁/枷锁流程。
0 0
原创粉丝点击