java方法上的synchronized到底锁的什么资源

本文深入探讨了Java中的`synchronized`关键字,通过实例代码展示了在静态和非静态方法上使用`synchronized`时锁住的资源。对于非静态方法,锁住的是对象实例(`this`),而对于静态方法,锁住的是类本身(`TestSynchronize.class`)。测试结果显示,静态方法间的`synchronized`关键字会竞争同一个类锁,而非静态方法则竞争同一对象实例锁。
摘要由CSDN通过智能技术生成

前言

我们都用过synchronized这个关键字,常见的使用方式是这样synchronized(资源){代码},这是显示的声明锁资源,很明显知道要竞争锁资源是什么。
我们也知道在两个不同方法上架synchrinized关键字,这两个方法在不同线程中会互相等待,他们好像获取的是同一个资源,那这个锁资源是什么呢?是方法的引用obj::method?下面我们来验证一下

声明一个加synchronized的类

public class TestSynchronize {
	static Object get1 = new Object();
	public synchronized void get() {

//		synchronized (this) {
		System.out.println(Thread.currentThread().getName()+"get得到锁"+this);
		try {
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
//		}
	}
	

	public synchronized void ge2t() {

		System.out.println(Thread.currentThread().getName()+"ge2t得到锁"+this);
		try {
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static synchronized void staticget() {
			System.out.println(Thread.currentThread().getName()+"staticget得到锁");
			try {
				TimeUnit.SECONDS.sleep(3);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}
	

	public static synchronized void staticge2t() {

		System.out.println(Thread.currentThread().getName()+"staticge2t得到锁");
		try {
			TimeUnit.SECONDS.sleep(3);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

执行代码测试

  1. 我们先看下非静态方法的情况
public static void main(String[] args) {
		TestSynchronize stu = new TestSynchronize();
		
		new Thread(()->{
			synchronized (stu) {
				
				System.out.println(Thread.currentThread().getName()+"获取锁"+stu+"\t"+System.currentTimeMillis());
				try {
					TimeUnit.SECONDS.sleep(5);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+"释放锁"+"\t"+System.currentTimeMillis());
			}
		},"a").start();;

		new Thread(()->{
			
			System.out.println(Thread.currentThread().getName()+"尝试"+"\t"+System.currentTimeMillis());
			stu.get();
			
			System.out.println(Thread.currentThread().getName()+"结束"+"\t"+System.currentTimeMillis());
		},"b").start();
		new Thread(()->{
			
			System.out.println(Thread.currentThread().getName()+"尝试"+"\t"+System.currentTimeMillis());
			stu.ge2t();
			
			System.out.println(Thread.currentThread().getName()+"结束"+"\t"+System.currentTimeMillis());
		},"c").start();
		
	}
a获取锁Test.Test.TestSynchronize@1d1ae28f	1635507748132
b尝试	1635507748133
c尝试	1635507748133
a释放锁	1635507753143
c\t ge2t得到锁Test.Test.TestSynchronize@1d1ae28f	1635507753143
c结束	1635507756155
b	 get得到锁Test.Test.TestSynchronize@1d1ae28f	1635507756155
b结束	1635507759166

我们看待a线程获取锁之后,b,c线程都在等待锁,c获取锁后b线程在等待锁

  1. 在看下静态方法上的synchronized
public static void main(String[] args) {
		new Thread(()->{
			synchronized (TestSynchronize.class) {

				System.out.println(Thread.currentThread().getName()+"获取锁"+TestSynchronize.class +"\t"+System.currentTimeMillis());
				try {
					TimeUnit.SECONDS.sleep(5);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName()+"释放锁"+"\t"+System.currentTimeMillis());
			}
		},"astatic").start();
		new Thread(()->{
			
			System.out.println(Thread.currentThread().getName()+"尝试"+"\t"+System.currentTimeMillis());
			TestSynchronize.staticget();
			
			System.out.println(Thread.currentThread().getName()+"结束"+"\t"+System.currentTimeMillis());
		},"estatic").start();
		new Thread(()->{
			
			System.out.println(Thread.currentThread().getName()+"尝试"+"\t"+System.currentTimeMillis());
			TestSynchronize.staticge2t();
			
			System.out.println(Thread.currentThread().getName()+"结束"+"\t"+System.currentTimeMillis());
		},"fstatic").start();
		
	}
astatic	获取锁class Test.Test.TestSynchronize	1635507551822
estatic	尝试 	1635507551822
fstatic	尝试	1635507551823
astatic	释放锁	1635507556825
fstatic\t staticge2t得到锁	1635507556825
fstatic	结束	1635507559834
estatic\t staticget得到锁	1635507559834
estatic	结束	1635507562843

我们可以看到astatic线程获取锁后,estatic fstatic两个线程中的静态方法都在等待锁,fstatic得到锁之后estatic 在等待fstatic释放锁。

结论

  1. 当在静态方法上加synchronized时,实际上锁的资源是class这个类等效代码是synchronized (TestSynchronize.class) ,所以两个静态方法都加synchronized关键字时竞争的是同一个锁资源。
  2. 当在普通方法上加锁时,实际上锁的是实体对象,也就是this,上面打印出来是TestSynchronize@1d1ae28f这个对象,所以两个普通方法竞争的也是同一个锁资源,也会互相等待。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

huihttp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值