Java中对对象加锁的方法和对类加锁的方法会不会互相阻塞?

Java中对对象加锁的方法和对类加锁的方法会不会互相阻塞?

今天面试遇到这么一个问题:对对象加锁的方法和对类加锁的方法会不会互相阻塞?

然后我参照了网上的一些博客内容,写了以下程序验证:

他们的结果是交错输出的,也就是说他们是不阻塞的。

那么为什么会成为这样子呢?

先说一个Synchronized的原理

Synchronized关键字在编译的时候,会在同步块前后形成一个monitorenter和monitorexit的字节码指令,这两个字节码都需要一个reference类型的参数来指明要加锁和解锁的对象,在执行moniterenter指令的时候,首先要先获取加锁的对象,如果这个对象没有被锁定,就会把对象头里边锁的计数器加1,执行monitroexit的时候就会把锁的对象减一。

在执行synchronized (Solution.class)进入代码块的时候,他是对Solution的Class对象加锁,Class对象是每次加载Class文件在JVM中生成的对象,每个类对应着一个Class对象,这个Class对象是实际存在的,因此在进入synchronized (Solution.class)同步代码块的时候,会将对象头中锁的计数器加一。对实例对象synchronized (this)进行加锁的时候,则会在实例对象的对象头的计数器里边加一。因此他们是不通的加锁对象,因此不会阻塞。

那么对使用不同加载器加载的类加锁会不会阻塞呢?

我正在验证,之后补上。

结果和程序如下
image-20211023124503822

public class Solution3 {
	
	static void run1() throws InterruptedException {
		synchronized (Solution.class) {
			for(int i=0;i<10;i++) {
				Thread.sleep(10);
				System.out.println(Thread.currentThread().getName());
			}
		}
	}
	void run2() throws InterruptedException {
		
		synchronized (this) {
			for(int i=0;i<10;i++) {
				Thread.sleep(10);
				System.out.println(Thread.currentThread().getName());
			}
		}
		
	}
	public static void main(String[] args) throws InterruptedException {
		Solution3 solution=new Solution3();
		new Thread(()->{
			try {
				Solution3.run1();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}).start();
		
		new Thread(()->{
			try {
				solution.run2();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}).start();
		
		Thread.sleep(2000);
	}
}


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值