synchronized底层的锁

本文详细介绍了Java中的锁机制,包括偏向锁、无锁、轻量级锁和重量级锁的概念及工作原理。通过实例演示了不同锁状态下对象的变化,并解释了如何通过代码观察这些状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主要分为以下的几个锁(偏向锁  无锁  轻量级锁  重量级锁

目录

主要分为以下的几个锁(偏向锁  无锁  轻量级锁  重量级锁)

偏向锁:大部分情况下,锁不仅仅不存在多线程竞争,而是总是由同一个线程多次获得,为了让线程获取锁的代价更低就引入了偏向锁。

没有开启偏向锁的情况下:

 无锁:一个对象如果没有被任何线程当做锁去使用,就是无锁状态。

​编辑

  轻量级锁: 一个对象如果被一个线程当做锁去使用,就是轻量级锁状态。

​编辑

 重量级锁:一个对象当做锁被一个线程持有,另外一个线程还继续去获取该锁,就是重量级锁。

开启偏向锁的情况下:

无锁可偏向

总结:


偏向锁:大部分情况下,锁不仅仅不存在多线程竞争,而是总是由同一个线程多次获得,为了让线程获取锁的代价更低就引入了偏向锁。

没有开启偏向锁的情况下:

 无锁:一个对象如果没有被任何线程当做锁去使用,就是无锁状态。

public class test2 {
	public static void main(String[] args) {
		A a=new A();
		String str = ClassLayout.parseInstance(a).toPrintable();//获取锁的状态
		System.out.println(str);
		//此时是无锁的状态
	}
}
class A{
	
}

   在value的下面第一行中    01代表了无锁的状态

  轻量级锁: 一个对象如果被一个线程当做锁去使用,就是轻量级锁状态。

public class test2 {
    public static void main(String[] args) throws InterruptedException {
		A a=new A();
		String str = ClassLayout.parseInstance(a).toPrintable();//获取锁的状态
		System.out.println(str);
		//此时是无锁的状态
		
		new Thread() {
			public void run() {
				//把a作为锁对象
				synchronized(a) {
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
			}
		}.start();
		
		Thread.sleep(10);//保证线程获取锁对象
		str = ClassLayout.parseInstance(a).toPrintable();//获取锁的状态
		System.out.println(str);//此时该锁的为轻量级锁
    }
}
class A{
	
}

 此时value下的8位二进制数的后两位是   00 ,则代表是轻量级锁。

 重量级锁:一个对象当做锁被一个线程持有,另外一个线程还继续去获取该锁,就是重量级锁。

public class test2 {
	public static void main(String[] args) throws InterruptedException {
		A a=new A();
		String str = ClassLayout.parseInstance(a).toPrintable();//获取锁的状态
		System.out.println(str);
		//此时是无锁的状态
		
		new Thread() {
			public void run() {
				//把a作为锁对象
				synchronized(a) {
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
			}
		}.start();
		
		Thread.sleep(10);//保证线程获取锁对象
		str = ClassLayout.parseInstance(a).toPrintable();//获取锁的状态
		System.out.println(str);//此时该锁的为轻量级锁
		
		//第二个线程
		new Thread() {
			public void run() {
				//把a作为锁对象
				synchronized(a) {
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
			}
		}.start();
		Thread.sleep(10);//保证线程获取锁对象
		str = ClassLayout.parseInstance(a).toPrintable();//获取锁的状态
		System.out.println(str);//此时该锁的为重量级锁。
		//此时有两个线程,第一个线程已经获取了锁且没有释放锁,
		//第二个线程要尝试获取该锁
	}
}
class A{
	
}

 此时value下的8位二进制数的后两位是   10,则代表是重量级锁。

开启偏向锁的情况下:

需要先进行修改

修改偏向锁的延迟时间的参数:-XX:BiasedLockingStartupDelay=0

无锁可偏向

public class test3 {
	public static void main(String[] args) throws InterruptedException {
		A a=new A();
		String str = ClassLayout.parseInstance(a).toPrintable();//获取锁的状态
		System.out.println(str);
	}
}

  此时value下的8位二进制数的后三位是   101,则代表是无锁可偏向锁。

轻量级锁可偏向

重级锁可偏向

public static void main(String[] args) throws InterruptedException {
		A a = new A();
		String str = ClassLayout.parseInstance(a).toPrintable();
		System.out.println(str);//101  无锁可偏向
		
		new Thread() {
			public void run() {
				synchronized(a) {
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
				
				/*
				 * 	显示的让当前线程不结束
				 * 	如果结束了,下一个线程的id和刚才这个线程的id是一样的。
				 */
				try {
					Thread.sleep(100000000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}.start();
		Thread.sleep(100);
		str = ClassLayout.parseInstance(a).toPrintable();
		System.out.println(str);//101  无锁可偏向
		
		Thread.sleep(1000);//保证上一个线程已经把任务执行完毕了
		new Thread() {
			public void run() {
				synchronized(a) {
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
		Thread.sleep(100);
		str = ClassLayout.parseInstance(a).toPrintable();
		System.out.println(str);//
		
		new Thread() {
			public void run() {
				synchronized(a) {
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();
		Thread.sleep(100);
		str = ClassLayout.parseInstance(a).toPrintable();
		System.out.println(str);//
	}
}

 

此时value下的8位二进制数的后三位是   000,且后面不为0,则代表是可偏向轻量锁。

第二个8位的二进制有具体的数字则说明有偏向锁的ID,可以方便线程找到偏向锁。

 

此时value下的8位二进制数的后三位是   010,且后面不为0,则代表是可偏向重量锁。

第二个8位的二进制有具体的数字则说明有偏向锁的ID,可以方便线程找到偏向锁。

总结:

没有开启偏向锁的情况下:

一个对象没有被作为锁对象,处于无锁状态

一个对象被一个线程获取作为锁对象,处于轻量级锁状态

一个线程已经持有了该锁对象,其他线程来争用,处于重量级锁状态。

开启偏向锁的情况下:

一个对象没有被作为锁对象,处于无锁可偏向状态。(对象头中没有记录线程ID)

一个对象被一个线程作为锁对象,处于轻量级锁状态。(对象头中记录了线程ID)

一个对象被一个线程作为锁对象,释放锁对象后(但是该线程没有消亡时),其他线                  程再获取该锁对象,则处于轻量级锁状态。

一个对象被一个线程作为锁对象,没有释放锁,其他线程也要获取该锁对象,就处                  于重量级锁状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值