标签:一个 stat oid new 成功 lock thread 无锁 bsp
synchronized默认采取非公平锁,锁偏向是指线程在释放锁后再次进入请求队列中等待获取锁时,虚拟机会优先唤醒该线程。并省去获取锁的操作,进行无锁操作。
代码:
public class BIasLockTest {
public static void main(String[] args) {
Object lock = new Object();
AtomicInteger num = new AtomicInteger();
for(int i = 0; i < 100; i++){
Thread t = new ThreadA("t" + i,lock,num);
t.start();
}
}
}
class ThreadA extends Thread{
private Object lock;
private AtomicInteger num;
public ThreadA(String name, Object lock,AtomicInteger num) {
super(name);
this.lock = lock;
this.num = num;
}
@Override
public void run() {
while(num.getAndIncrement() < 100){
synchronized (lock){
System.out.print(Thread.currentThread().getName() + " ");
}
}
}
}
输出片段:
t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t0 t4 t4 t4 t4 t4 t4 t4 t4 t4 t4 t3 t3 t3 t3 t3 t3 t3 t3 t3 t3 t3 t3
t3 t3 t4 t4 t4 t4 t0 t55 t2 t44 t1 t8 t7 t3
当锁竞争比较激烈,偏向锁就会失效,例如这一段:t4 t4 t4 t0 t55 t2 t44 t1 t8 t7 t3
基本上每次获取锁的线程都不一样,偏向锁失效后,会升级为轻量级锁。
轻量级锁将对象头部作为指针指向持有锁的线程堆栈的内部,来判断一个线程是否持有对象锁。
线程获取轻量级锁成功后可以进入临界区。获取失败则膨胀为重量级锁。
轻量级锁膨胀为重量级锁后,为了避免线程真实的在操作系统层面挂起,虚拟机让线程执行几个空循环,目的是等待其他线程释放锁资源。
空循环以后,如果获取锁成功,则自旋成功,如果依旧获取失败,则线程在操作系统层面挂起,等待被唤醒。
锁消除涉及逃逸分析,逃逸分析是观察某一个变量是否会逃出某一个作用域。
例如在方法中存在一个Vector类型的临时变量,这个临时变量只在这个方法中使用,那个对这个临时变量的任何操作都只会在当前线程进行。这类无意义的加锁完全可以去掉。
参考:
《实战Java高并发程序设计》
标签:一个 stat oid new 成功 lock thread 无锁 bsp
原文地址:https://www.cnblogs.com/simple-ly/p/11123650.html