java之Synchronized(锁住对象和锁住代码)

1、问题

Synchronized我们一般都知道是锁,但是我们怎么区分是锁对象还是锁代码呢?

 


2、测试Demo

package leetcode.chenyu.test;

public class Synchronized {
	
	 class Test {
		public synchronized  void testFirst() {
			print("testFirst");
		}
		
		public void testSecond() {
			synchronized(this) {
				print("testSecond");
			}
		}
		
		public void testThird() {
			synchronized(Test.class) {
				print("testThird");
			}
		}
		
		public  void print(String method) {
			System.out.println(method + "start");
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(method + "end");
		}
	}
	
	
	class TestThread extends Thread {
		
		public int mType = 0;
		public Test mTest = null;
		
		public TestThread(int type, Test test) {
			this.mType = type;
			this.mTest = test;
		}
		
		public void run() {
			if (mTest == null) {
				if (mType == 1) {
					Test test = new Test();
					test.testFirst();
				}
				else if (mType == 2) {
					Test test = new Test();
					test.testSecond(); 
				} 
				else if (mType == 3) {
					Test test = new Test();
					test.testThird(); 
				}
			} else {
				if (mType == 1) {
					mTest.testFirst();
				}
				else if (mType == 2) {
					mTest.testSecond(); 
				}
				else if (mType == 3) {
					mTest.testThird(); 
				}
			}
		}
	}
	
	
	public static void main(String[] args) {
		Synchronized syn = new Synchronized();
		Test test = syn.new Test();
			for (int i = 0; i < 5; ++i) {
				syn.new TestThread(1, null).start();
		}
	}
}

 


3、运行结果和分析

 

1)、按照上面的运行结果

testFirststart
testFirststart
testFirststart
testFirststart
testFirststart
testFirstend
testFirstend
testFirstend
testFirstend
testFirstend

 

2)、把for循环里面的代码换如下

 

syn.new TestThread(2, null).start();

运行结果如下

testSecondstart
testSecondstart
testSecondstart
testSecondstart
testSecondstart
testSecondend
testSecondend
testSecondend
testSecondend
testSecondend

对于上面1)、2)、两种情况,synchronized(this)以及非static的synchronized方法,只能防止多个线程同时执行同一个对象的同步代码段,锁的是对象,也就是锁的本身this, 由于每个线程都新构建了一个新的对象,所以加了synchronized没有锁住。

 

3)、把for循环里面的代码换如下

syn.new TestThread(1, test).start();
syn.new TestThread(2, test).start();

运行结果都一样如下

testSecondstart
testSecondend
testSecondstart
testSecondend
testSecondstart
testSecondend
testSecondstart
testSecondend
testSecondstart
testSecondend

这里由于我们几个现场都共用一个对象,所以对象固定了,所以就锁住了,其它线程在没有释放锁的时候,进不来。

4)、把for循环里面的代码换如下

syn.new TestThread(3, null).start();
syn.new TestThread(3, test).start();

结果都如下

testThirdstart
testThirdend
testThirdstart
testThirdend
testThirdstart
testThirdend
testThirdstart
testThirdend
testThirdstart
testThirdend

synchronized(Test.class)实现了全局锁的效果,不管对象是不是一样的,都是同样的效果,就锁住代码了

 

我么一般用这个比较多。

 

 

 

 

4、总结

1、synchronized加在非静态方法前和synchronized(this)都是锁住了这个类的对象,如果多线程访问,对象不同,就锁不住,对象固定是一个,就可锁住。

2、synchronized(类名.class)和加在静态方法前,是锁住了代码块,不管多线程访问的时候对象是不是同一个,能缩小代码段的范围就尽量缩小,能在代码段上加同步就不要再整个方法上加同步,缩小锁的粒度。

 

 

 

 

 

 

 


4、总结

  • 3
    点赞
  • 12
    收藏
  • 打赏
    打赏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:猿与汪的秘密 设计师:我叫白小胖 返回首页
评论

打赏作者

码莎拉蒂 .

你的鼓励是我最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值