哒哒哒
2017-07-21 15:50 Qin奋 阅读(259) 评论(0) 收藏 举报1. 多线程的3中运行方式:
2. synchronized是一个重量级锁
3. sychronized的锁类型 和 位置
java 为每个类实例和类都设置了一个锁并且遵循一定的锁机制。
在分析sychronized 逻辑是,关键点就是分析出提供锁的对象是哪个?实例,还是类
Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:
1. 普通同步方法,锁是当前实例对象
2. 静态同步方法,锁是当前类的class对象
3. 同步方法块,锁是括号里面的对象(某个实例对象或者class对象)
4.synchronized 实现原理(javap filename.class)
同步代码块:monitorenter指令插入到同步代码块的开始位置,monitorexit指令插入到同步代码块的结束位置。
每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令
时尝试获取monitor的所有权,过程如下:
1.如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。
2.如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.
3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。
执行monitorexit的线程必须是objectref所对应的monitor的所有者。
monitor的进入数减1,如果减1后进入数为0。
同步方法: synchronized方法则会被翻译成普通的方法调用和返回指令如:invokevirtual、areturn指令,在VM字节码层面并没有任何
特别的指令来实现被synchronized修饰的方法,而是在Class文件的方法表中将该方法的access_flags字段中的synchronized
标志位置1。如果设置了,执行线程将先获取monitor。并没有通过指令monitorenter和monitorexit来完成
Java对象头和monitor是实现synchronized的基础:
Hotspot虚拟机的对象头主要包括两部分数据:Mark Word(标记字段)、Klass Pointer(类型指针)。
其中Klass Point是是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例,
Mark Word用于存储对象自身的运行时数据,它是实现轻量级锁和偏向锁的关键,所以下面将重点阐述
Mark Word用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持
有的锁、偏向线程 ID、偏向时间戳等等。
Monitor 是线程私有的数据结构,每一个线程都有一个可用monitor record列表,同时还有一个全局的可用列表。
每一个被锁住的对象都会和一个monitor关联(对象头的MarkWord中的LockWord指向monitor的起始地址),
同时monitor中有一个Owner字段存放拥有该锁的线程的唯一标识,表示该锁被这个线程占用。其结构如下:
JDK1.6后对synchronized的优化:
自旋锁,自适应自旋锁
锁消除
锁粗化
轻量级锁 偏向锁 锁释放
JAVA线程操作之 wait notify notifyAll condition,生产者消费者
JAVA线程操作之 interruppt isInterrupted interruppted
(1)interrupt:调用此方法的线程的状态属性置为“interrupted”,interrupt()并不会中断一个正在运行的线程,或者说让一个running中的线程放弃CPU。
调用此方法,如果线程处于阻塞状态,那么线程将会抛出InterruptedException异常
应用场景:
*this.interruppt()线程本身并不会立刻终止。程序员需要根据这个状态属性,自行决定如何进行线程的下一步活动。
因为Core Java中有这样一句话:"没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为
了引起该线程的注意,被中断线程可以决定如何应对中断 "。所以Thread.stop(),suspend(), resume(),runFinalizersOnExit()
被废弃了。
*使用Thread.interrupt()中断可能永久的阻塞线程(Object.wait()、ServerSocket.accept())。
或者需要用某种机制使得线程更早地退出被阻塞的状态.
(2)isInterrupted:线程是否中断 native 方法
(3)interrupted:*返回线程的上次的中断状态,并清除中断状态。就是如果状态位是true(isInterrupted()=true),则interrupted()返回的
结果是true,但是同时把状态为设置成false,再调用isInterrupted()会返回false.
*只有当前线程才能清除自己的中断位(对应interrupted()方法)
意思是interrupted()不可能像 TreadA.isInterrupted() 或者TreadA.interrupt()一样使用,而是在自己的run方法里面
直接interrupted();
浙公网安备 33010602011771号