栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

synchronized锁的什么资源
  • 前言
  • 声明一个加synchronized的类
  • 执行代码测试
  • 结论

前言

我们都用过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
ct 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
fstatict staticge2t得到锁	1635507556825
fstatic	结束	1635507559834
estatict staticget得到锁	1635507559834
estatic	结束	1635507562843

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

结论
  1. 当在静态方法上加synchronized时,实际上锁的资源是class这个类等效代码是synchronized (TestSynchronize.class) ,所以两个静态方法都加synchronized关键字时竞争的是同一个锁资源。
  2. 当在普通方法上加锁时,实际上锁的是实体对象,也就是this,上面打印出来是TestSynchronize@1d1ae28f这个对象,所以两个普通方法竞争的也是同一个锁资源,也会互相等待。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/356455.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号