[TOC]一、概念LockSupport是JDK中比较底层的类,用来创建锁和其他同步工具类的基本线程阻塞原语。park,unpark这两个方法都是LockSupport类名下的方法,park用来暂停线程,unpark用来将暂停的线程恢复。先park再unpark的方式是容易理解的。但还有一个场景,先unpark后再次执行park方法,也不会阻塞调用了park方法的线程。理解为park方法就是校验获取一个通行令牌,而unpark方法是获取到一个通行令牌的过程。先执行unpark方法,代表先获得了通行令牌。那么在另一个线程调用park方法时,校验到这个令牌存在,消耗掉这个令牌然后就可以继续往...
[TOC]一、基本概念保护性暂停(Guarded Suspension):用在一个线程等待另一个线程的执行结果时使用。保护性暂停的暂停就是当条件不满足的时候就去进行wait等待。要点有一个结果需要从一个线程传递到另一个线程,让它们关联同一个GuardedObject。如果有结果不断从一个线程到另一个线程那么此时就不能使用这个保护性暂停模式了,可以使用消息队列(见生产者/消费者)。JDK中,join的实现、Future的实现,采用的就是此模式。(用join一个线程等待另一个线程结束就可以拿到结果了,其实这也是保护性线程的一个应用)因为要等待另一方的结果,因此归类到同步模式。线程2产生这个结...
[TOC]一、原理分析Owner 线程发现条件不满足,调用 wait 方法,即可进入 WaitSet 变为 WAITING 状态BLOCKED 和 WAITING 的线程都处于阻塞状态,不占用 CPU 时间片BLOCKED 线程会在 Owner 线程释放锁时唤醒WAITING 线程会在 Owner 线程调用 notify 或 notifyAll 时唤醒,但唤醒后并不意味者立刻获得锁,仍需进入EntryList 重新竞争二、API介绍方法说明obj.wait()wait方法让进入object监视器的线程到waitSet等待。wait后会释放对象锁,让其他线程竞争。obj.wait(Long...
[TOC]一、偏向锁概念轻量级锁在没有竞争时(就自己这个线程),每次重入仍然需要执行 CAS操作。Java 6中引入了偏向锁来做进一步优化:只有第一次使用CAS将线程ID设置到对象的Mark Word头,之后发现这个线程ID是自己的就表示没有竞争,不用重新CAS。以后只要不发生竞争,这个对象就归该线程所有。升级为轻量级锁的情况 (会进行偏向锁撤销) : 获取偏向锁的时候, 发现线程ID不是自己的, 此时通过CAS替换操作, 操作成功了, 此时该线程就获得了锁对象。( 此时是交替访问临界区, 撤销偏向锁, 升级为轻量级锁)。升级为重量级锁的情况 (会进行偏向锁撤销) : 获取偏向锁的时候,...
[TOC]一、轻量级锁轻量级锁的使用场景:如果一个对象虽然有多线程要加锁,但加锁的时间是错开的(也就是没有竞争),那么可以 使用轻量级锁来优化。轻量级锁对使用者是透明的,即语法仍然是 synchronized示例假设有两个方法同步块,利用同一个对象加锁static final Object obj = new Object(); public static void method1() { synchronized (obj) { // 同步块 A method2(); } } public static void method2() { ...
[TOC]一、Java对象头HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头(Header)、实例数据(Instance Data)和对齐填充(Padding)。HotSpot虚拟机的对象头包括三部分信息:Mark Word指向类的指针数组长度普通对象以 32 位虚拟机为例Klass Word:指向对象的类型(一个指针找到它的类对象)一个int 类型占4个字节,而一个Integer对象占8 + 4个字节数组对象说明Object的对象头,分为两部分第一部分是Mark Word,用来存储对象的运行时数据比如:hashcode,GC分代年龄,锁状态,持有锁信息,偏向锁的t...
[TOC]一、卖票问题练习总共有1000张票,通过循环的方式开启多个线程模拟多人买票场景/** * 卖票问题练习 */ @Slf4j(topic = "c.ExerciseSell") public class ExerciseSell { public static void main(String[] args) throws InterruptedException { //模拟多人买票 TicketWindow window = new TicketWindow(1000); //所有线程的集合 ...
[TOC]前言分析线程是否安全,先对类的成员变量,类变量,局部变量进行考虑,如果变量会在各个线程之间共享,那么就得考虑线程安全问题了,如果变量A引用的是线程安全类的实例,并且只调用该线程安全类的一个方法,那么该变量A是线程安全的的。示例一Servlet运行在Tomcat环境下,只有一个实例,会被tomcat的多个线程共享,因此其中的成员变量都会存在共享问题。public class MyServlet extends HttpServlet { // 是否安全?否(HashMap不是线程安全类) Map<String,Object> map = new Has...
[TOC]一、成员变量和静态变量是否线程安全?如果它们没有共享,则线程安全如果它们被共享了,根据它们的状态是否能够改变,又分两种情况如果只有读操作,则线程安全如果有读写操作,则这段代码是临界区,需要考虑线程安全二、局部变量是否线程安全?局部变量是线程安全的但局部变量引用的对象则未必如果该对象没有逃离方法的作用范围,它是线程安全的如果该对象逃离方法的作用范围,需要考虑线程安全三、局部变量线程安全分析示例代码public static void test1() { int i = 10; i++; }每个线程调用 test1() 方法时局部变量 i,会在每个线程的栈帧内存中被...