测试:synchronized究竟是个什么东西?

只知道它是一个锁.但是怎么使用?效果又是如何?

关于多线程测试,请查看我另一篇日志:https://blog.youkuaiyun.com/dmw412724/article/details/80106514

一、不加synchronized

demo类

public class SynchronizedDemo {
	private Random random = new Random();
	
	public void aaa(){
		System.out.println("aaa start =" + Thread.currentThread().getName());	
		System.out.println("aaa end =" + Thread.currentThread().getName());
	}
}

开启10个线程操作这个段代码:(以后所有都是开启10个线程)

public static void go(){
		SynchronizedDemo demo = new SynchronizedDemo();
		demo.aaa();
	}

打印结果:

aaa start =Thread-4
aaa end =Thread-4
aaa start =Thread-8
aaa end =Thread-8
aaa start =Thread-7
aaa end =Thread-7
aaa start =Thread-1
aaa start =Thread-5
aaa start =Thread-6
aaa start =Thread-2
aaa end =Thread-6
aaa end =Thread-5
aaa end =Thread-1
aaa start =Thread-0
aaa start =Thread-9
aaa start =Thread-3
aaa end =Thread-9
aaa end =Thread-0

打印速度秒出。可以看到结果紊乱。

二、然后我们在demo里方法里加入synchronized

public synchronized void aaa(){
		System.out.println("aaa start =" + Thread.currentThread().getName());	
		System.out.println("aaa end =" + Thread.currentThread().getName());
	}

执行同上。
打印结果:
aaa start =Thread-5
aaa start =Thread-6
aaa end =Thread-6
aaa start =Thread-3
aaa start =Thread-0
aaa start =Thread-1
aaa start =Thread-2
aaa start =Thread-8
aaa start =Thread-4
aaa start =Thread-9
aaa start =Thread-7
aaa end =Thread-9
aaa end =Thread-4
aaa end =Thread-8
aaa end =Thread-2
aaa end =Thread-1
aaa end =Thread-0
aaa end =Thread-3

现象:秒出,紊乱。

三、方法里加入synchronized,但执行时使用同一对象。

demo同上。

执行先创建一个全局变量

static SynchronizedDemo demo = new SynchronizedDemo();
	public static void go(){
		demo.aaa();
	}

打印结果:

aaa start =Thread-8
aaa end =Thread-8
aaa start =Thread-9
aaa end =Thread-9
aaa start =Thread-7
aaa end =Thread-7
aaa start =Thread-6
aaa end =Thread-6
aaa start =Thread-3
aaa end =Thread-3
aaa start =Thread-5
aaa end =Thread-5
aaa start =Thread-4
aaa end =Thread-4
aaa start =Thread-0
aaa end =Thread-0
aaa start =Thread-2
aaa end =Thread-2
aaa start =Thread-1
aaa end =Thread-1

现象:秒出,有序。

难道synchronized只对同一对象有作用?接着测试

四、把synchronized从方法上移到方法中,加锁为this。

demo:

public  void aaa(){
		synchronized (this) {
			System.out.println("aaa start =" + Thread.currentThread().getName());	
			System.out.println("aaa end =" + Thread.currentThread().getName());
		}
		
	}

执行同上。

打印结果:

aaa start =Thread-8
aaa end =Thread-8
aaa start =Thread-9
aaa end =Thread-9
aaa start =Thread-7
aaa end =Thread-7
aaa start =Thread-6
aaa end =Thread-6
aaa start =Thread-5
aaa end =Thread-5
aaa start =Thread-4
aaa end =Thread-4
aaa start =Thread-3
aaa end =Thread-3
aaa start =Thread-2
aaa end =Thread-2
aaa start =Thread-1
aaa end =Thread-1
aaa start =Thread-0
aaa end =Thread-0

现象,秒出,有序。

五、加锁由this改为“aaa”一个字符串。

demo
public  void aaa(){
		synchronized ("aaa") {
			System.out.println("aaa start =" + Thread.currentThread().getName());	
			System.out.println("aaa end =" + Thread.currentThread().getName());
		}
		
	}

执行同上

打印同上

现象:秒出有序

六、加锁“aaa”,但是使用不同的对象。

demo同上

执行:

public static void go(){
		 SynchronizedDemo demo = new SynchronizedDemo();
		 demo.aaa();
	}

打印:

aaa start =Thread-8
aaa end =Thread-8
aaa start =Thread-6
aaa end =Thread-6
aaa start =Thread-3
aaa end =Thread-3
aaa start =Thread-0
aaa end =Thread-0
aaa start =Thread-9
aaa end =Thread-9
aaa start =Thread-2
aaa end =Thread-2
aaa start =Thread-1
aaa end =Thread-1
aaa start =Thread-4
aaa end =Thread-4
aaa start =Thread-5
aaa end =Thread-5
aaa start =Thread-7
aaa end =Thread-7

现象:秒出有序。

为了验证其非特殊性,demo修改下,进行睡眠3秒

public  void aaa(){
		synchronized ("aaa") {
			System.out.println("aaa start =" + Thread.currentThread().getName());
			try {
				Thread.currentThread().sleep(3000);
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
			System.out.println("aaa end =" + Thread.currentThread().getName());
		}
		
	}

现象:延时,有序。

七、好像有点头绪了,换锁this,使用不同的对象。

demo
public  void aaa(){
		synchronized (this) {
			System.out.println("aaa start =" + Thread.currentThread().getName());
			try {
				Thread.currentThread().sleep(3000);
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
			System.out.println("aaa end =" + Thread.currentThread().getName());
		}
		
	}

执行同上,

打印:

aaa start =Thread-1
aaa start =Thread-0
aaa start =Thread-5
aaa start =Thread-8
aaa start =Thread-7
aaa start =Thread-2
aaa start =Thread-9
aaa start =Thread-3
aaa start =Thread-6
aaa start =Thread-4
aaa end =Thread-5
aaa end =Thread-7
aaa end =Thread-8
aaa end =Thread-0
aaa end =Thread-1
aaa end =Thread-3
aaa end =Thread-4
aaa end =Thread-6
aaa end =Thread-2
aaa end =Thread-9

现象:延时,无序!

这说明一个很重要的结论:同一个类的同一个方法,在方法内部如果使用synchronized的锁相同,那么会互斥,必须一个走完之后走。而在方法上面声明的synchronized,却只能在同一个类的同一个对象的同个方法里互斥,那么揣测,方法上面声明的锁实际上就是关键字this,而this代表各个对象。

接下来将证明,同一个类的多个方法都有synchronized,同时执行各个方法会有什么样的现象???

八、更换Demo,写两个方法,都带那个synchronized关键字。

demo

public class SynchronizedDemo {
	private Random random = new Random();

	public synchronized void aaa(int i) {
		System.out.println("aaa start =" + i);
		try {
			Thread.currentThread().sleep(3000);
		} catch (InterruptedException e) {

			e.printStackTrace();
		}
		System.out.println("aaa end =" + i);
	}
	public synchronized void bbb(int i) {
		System.out.println("bbb start =" + i);
		try {
			Thread.currentThread().sleep(3000);
		} catch (InterruptedException e) {
			
			e.printStackTrace();
		}
		System.out.println("bbb end =" + i);
	}

	public void ccc() {
		int nextInt = random.nextInt(1000);
		if (nextInt % 2 == 0) {
			bbb(nextInt);
		} else {
			aaa(nextInt);
		}
	}

}

这个类就是我会执行ccc(),ccc里随机执行aaa()或者bbb(),aaa和bbb上面都有关键字

执行:

public static void go(){
		 SynchronizedDemo demo = new SynchronizedDemo();
		 demo.ccc();
	}

由于是不同的对象,所以推测打印紊乱。

打印:

aaa start =453
bbb start =552
bbb start =298
aaa start =131
bbb start =170
bbb start =548
aaa start =11
bbb start =664
bbb start =76
aaa start =669
aaa end =453
aaa end =669
aaa end =11
bbb end =76
bbb end =664
bbb end =548
bbb end =170
bbb end =552
bbb end =298
aaa end =131

现象:延时,紊乱。

九、使用同一个对象测试。

demo同上

执行:

static SynchronizedDemo demo = new SynchronizedDemo();
	public static void go(){
		 demo.ccc();
	}

打印:

bbb start =438
bbb end =438
aaa start =769
aaa end =769
aaa start =437
aaa end =437
bbb start =684
bbb end =684
aaa start =857
aaa end =857
aaa start =433
aaa end =433
aaa start =243
aaa end =243
aaa start =929
aaa end =929
aaa start =911
aaa end =911
bbb start =562
bbb end =562

结果:延时,有序。

看来锁对于不同的方法也有一定的效果,为了完善这个结论,要做更多的测试,

九、将方法声明上的关键字移到方法内部,同时均使用“ccc”作为锁,试试。

执行同上。

打印结果,同上。

延时有序。

十、分别使用不同的锁试试。

demo

public class SynchronizedDemo {
	private Random random = new Random();

	public  void aaa(int i) {
		synchronized ("aaa") {
			System.out.println("aaa start =" + i);
			try {
				Thread.currentThread().sleep(3000);
			} catch (InterruptedException e) {

				e.printStackTrace();
			}
			System.out.println("aaa end =" + i);
		}
		
	}
	public synchronized void bbb(int i) {
		synchronized ("bbb") {
			System.out.println("bbb start =" + i);
			try {
				Thread.currentThread().sleep(3000);
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
			System.out.println("bbb end =" + i);
		}
		
	}

	public void ccc() {
		int nextInt = random.nextInt(1000);
		if (nextInt % 2 == 0) {
			bbb(nextInt);
		} else {
			aaa(nextInt);
		}
	}

}

执行同上

打印:

bbb start =942
aaa start =291
aaa end =291
bbb end =942
aaa start =269
bbb start =556
aaa end =269
bbb end =556
aaa start =827
bbb start =710
aaa end =827
bbb end =710
aaa start =767
bbb start =624
bbb end =624
aaa end =767
bbb start =680
aaa start =87
bbb end =680
aaa end =87

结果:这个结果其实不是紊乱,而是有序的。实质是aaa的锁对所有aaa有用,bbb的锁对所有bbb有用。但是aaa和bbb是没有关系的。aaa和bbb同时只能各自执行一个,执行完成后释放锁,下一对aaa和bbb各自再占用锁执行,依次类推。

十一、不同的对象使相同的锁试试。

结果:

延时,有序。

结论2.同一个类的方法,只要锁相同,那么他们之间便是有序执行,并不局限于同一对象。

接下来,我们来看看,不同的类里使用这个打字恶心的关键字会发生什么样的情况?

十二、不同的类的不同对象的方法,使用相同的锁(使用不同的锁就不看了,推测紊乱)。

demo1

public class SynAaa {
	public void aaa(int i){
		synchronized ("lock") {
			System.out.println("aaa start =" + i);
			try {
				Thread.currentThread().sleep(3000);
			} catch (InterruptedException e) {

				e.printStackTrace();
			}
			System.out.println("aaa end =" + i);
		}
	}
}

demo2

public class SynBbb {
	public void bbb(int i){
		synchronized ("lock") {
			System.out.println("bbb start =" + i);
			try {
				Thread.currentThread().sleep(3000);
			} catch (InterruptedException e) {

				e.printStackTrace();
			}
			System.out.println("bbb end =" + i);
		}
	}
}

执行:

static Random random = new Random();
	public static void go(){
		int nextInt = random.nextInt(1000);
		if (nextInt % 2 == 0) {
			new SynAaa().aaa(nextInt);
		} else {
			new SynBbb().bbb(nextInt);
		}
	}

结果:

aaa start =352
aaa end =352
bbb start =47
bbb end =47
bbb start =103
bbb end =103
bbb start =257
bbb end =257
bbb start =711
bbb end =711
bbb start =323
bbb end =323
aaa start =240
aaa end =240
bbb start =439
bbb end =439
aaa start =794
aaa end =794
aaa start =136
aaa end =136

然而,我日了狗,延时、有序!!!

我靠!!!锁是全局的!全局的!全局的!!!

这就意味着,在任何地方,使用同一把锁的所有方法,必须排队执行,我靠,我赶紧修改代码去。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值