标签:一个 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