只知道它是一个锁.但是怎么使用?效果又是如何?
关于多线程测试,请查看我另一篇日志: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,使用不同的对象。
demopublic 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
然而,我日了狗,延时、有序!!!
我靠!!!锁是全局的!全局的!全局的!!!
这就意味着,在任何地方,使用同一把锁的所有方法,必须排队执行,我靠,我赶紧修改代码去。