编程语言
首页 > 编程语言> > 【并发编程】synchronized的偏向锁、轻量级锁、重量级锁详解

【并发编程】synchronized的偏向锁、轻量级锁、重量级锁详解

作者:互联网

内存布局对应对应的锁状态

内存布局对应对应的锁状态.png

先说锁状态的变化结论

锁状态的变化流程图.png

偏向锁

偏向锁延迟偏向

//关闭延迟开启偏向锁
-XX:BiasedLockingStartupDelay=0
//禁止偏向锁
-XX:-UseBiasedLocking 

延迟开启偏向锁.png

偏向锁在无竞争的时候一直是偏向锁

public static void main(String[] args) throws InterruptedException {
		log.debug(Thread.currentThread().getName() + "最开始的状态。。。\n"
				+ ClassLayout.parseInstance(new Object()).toPrintable());
		// HotSpot 虚拟机在启动后有个 4s 的延迟才会对每个新建的对象开启偏向锁模式
		Thread.sleep(4000);
		Object obj = new Object();

		new Thread(new Runnable() {
			@Override
			public void run() {
				log.debug(
						Thread.currentThread().getName() + "开始执行准备获取锁。。。\n" + ClassLayout.parseInstance(obj).toPrintable());
				synchronized (obj) {
					log.debug(Thread.currentThread().getName() + "获取锁执行中。。。\n"
							+ ClassLayout.parseInstance(obj).toPrintable());
				}
				log.debug(Thread.currentThread().getName() + "释放锁。。。\n" + ClassLayout.parseInstance(obj).toPrintable());
			}
		}, "thread1").start();

		Thread.sleep(5000);
		log.debug(Thread.currentThread().getName() + "结束状态。。。\n" + ClassLayout.parseInstance(obj).toPrintable());
	}

偏向锁在无竞争.png

在同步代码块外调用hashCode()方法

同步代码块外调用hashCode()结果.png

在同步代码块内调用hashCode()方法

同步代码块内调用hashCode()结果.png

偏向锁撤销:自己验证wait和notify

轻量级锁

模拟竞争不激烈的场景

@Slf4j
public class TestMemory {

	public static void main(String[] args) throws InterruptedException {
		log.debug(Thread.currentThread().getName() + "最开始的状态。。。\n"
				+ ClassLayout.parseInstance(new Object()).toPrintable());
		// HotSpot 虚拟机在启动后有个 4s 的延迟才会对每个新建的对象开启偏向锁模式
		Thread.sleep(4000);
		Object obj = new Object();

		Thread thread1 = new Thread(new Runnable() {
			@Override
			public void run() {
				log.debug(Thread.currentThread().getName() + "开始执行thread1。。。\n"
						+ ClassLayout.parseInstance(obj).toPrintable());
				synchronized (obj) {
					log.debug(Thread.currentThread().getName() + "获取锁执行中thread1。。。\n"
							+ ClassLayout.parseInstance(obj).toPrintable());
				}
				log.debug(Thread.currentThread().getName() + "释放锁thread1。。。\n"
						+ ClassLayout.parseInstance(obj).toPrintable());
			}
		}, "thread1");
		thread1.start();

		// 控制线程竞争时机
		Thread.sleep(1);

		Thread thread2 = new Thread(new Runnable() {
			@Override
			public void run() {
				log.debug(Thread.currentThread().getName() + "开始执行thread2。。。\n"
						+ ClassLayout.parseInstance(obj).toPrintable());
				synchronized (obj) {
					log.debug(Thread.currentThread().getName() + "获取锁执行中thread2。。。\n"
							+ ClassLayout.parseInstance(obj).toPrintable());
				}
				log.debug(Thread.currentThread().getName() + "释放锁thread2。。。\n"
						+ ClassLayout.parseInstance(obj).toPrintable());
			}
		}, "thread2");
		thread2.start();

		Thread.sleep(5000);
		log.debug(Thread.currentThread().getName() + "结束状态。。。\n" + ClassLayout.parseInstance(obj).toPrintable());
	}
}


竞争不激烈的场景的运行结果

轻量级锁结果.png

重量级锁

模拟竞争激烈的场景

// 控制线程竞争时机
Thread.sleep(1);

竞争激烈的场景的运行结果

重量级锁结果.png

结束语

标签:obj,synchronized,Thread,parseInstance,详解,轻量级,debug,偏向,toPrintable
来源: https://www.cnblogs.com/zfcq/p/15856884.html