synchronized锁的使用
synchronized可以使用在方法和代码块中, 使用的方式不同锁代表的含义不同, 下面将从几个方面进行介绍.
- 普通方法
- 静态方法
- 代码块synchronized(this)
- 代码块synchronized(*.class)
结论
- 在使用synchronized关键字中锁主要分为两类, 一种是对象锁, 另一种类锁
- 普通加锁方法和synchronized(this)都是对象锁, 静态加锁方法和synchronized(*.class)都是类锁
- 对象锁: 同一对象持有锁, 相同对象等待, 其他对象不受影响; 不同对象持有锁, 互不影响.
- 类锁: 类锁时, 只要该类的对象持有锁, 无论是否为同一对象访问静态同步方法时都等待, 访问非静态同步方法不受影响.
- 对象锁和类锁互相不影响
测试代码及过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package com.liuzhihang.tool.sync;
public class SyncMainTest {
public static void main(String[] args) { SyncTest syncTest1 = new SyncTest(); new Thread(() -> syncTest1.methodA(), "线程 01 ").start(); new Thread(() -> syncTest1.methodB(), "线程 02 ").start();
} }
class SyncTest {
void methodA() {
System.out.println(Thread.currentThread().getName() + "start"); try { System.out.println(Thread.currentThread().getName() + "sleep"); Thread.sleep(500); } catch (InterruptedException e) { } System.out.println(Thread.currentThread().getName() + "end"); }
void methodB() {
System.out.println(Thread.currentThread().getName() + "start"); try { System.out.println(Thread.currentThread().getName() + "sleep"); Thread.sleep(300); } catch (InterruptedException e) { } System.out.println(Thread.currentThread().getName() + "end"); }
}
|
以上为一个简单的测试代码, 指使用两个线程分别调用两个方法, 通过打印结果可以看出顺序是乱序的, 其中线程的 start() 顺序并不代表线程的执行顺序, 在下面测试中假设是 “线程01” 先执行.
1.A B 方法分别添加synchronized关键字 + 同一对象
1 2 3 4 5 6 7 8 9
| class SyncTest { synchronized void methodA() { } synchronized void methodB() { }
}
|
结论: 方法 A 阻塞, 方法 B 等待 A 执行完毕后才继续执行.
2.A B 方法分别添加synchronized关键字 + 不同对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class SyncMainTest {
public static void main(String[] args) { SyncTest syncTest1 = new SyncTest(); SyncTest syncTest2 = new SyncTest(); new Thread(() -> syncTest1.methodA(), "线程 01 ").start(); new Thread(() -> syncTest2.methodB(), "线程 02 ").start();
} } class SyncTest { synchronized void methodA() { } synchronized void methodB() { }
}
|
结论: 方法 A 阻塞, 方法 B 不受影响.
3.A 方法分别添加synchronized关键字 B方法不添加
1 2 3 4 5 6 7 8 9
| class SyncTest { synchronized void methodA() { } void methodB() { }
}
|
结论: 方法 A 阻塞, 方法 B 不受影响.
4.A B 方法分别添加 static synchronized + 不同对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class SyncMainTest {
public static void main(String[] args) { SyncTest syncTest1 = new SyncTest(); SyncTest syncTest2 = new SyncTest(); new Thread(() -> syncTest1.methodA(), "线程 01 ").start(); new Thread(() -> syncTest2.methodB(), "线程 02 ").start();
} } class SyncTest { static synchronized void methodA() { } static synchronized void methodB() { }
}
|
结论: 方法 A 阻塞, 方法 B 等待 A结束后继续执行.
5.A 方法添加 static synchronized, B 方法添加 synchronized + 不同对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class SyncMainTest {
public static void main(String[] args) { SyncTest syncTest1 = new SyncTest(); SyncTest syncTest2 = new SyncTest(); new Thread(() -> syncTest1.methodA(), "线程 01 ").start(); new Thread(() -> syncTest2.methodB(), "线程 02 ").start();
} } class SyncTest { static synchronized void methodA() { } synchronized void methodB() { }
}
|
结论: 方法 A 阻塞, 方法 B 不受影响.
6.A B 方法内添加 synchronized(this)
1 2 3 4 5 6 7 8 9 10 11 12 13
| class SyncTest { void methodA() { synchronized (this) { } } void methodB() { synchronized (this) { } }
}
|
结论: 同一对象 A 阻塞 B等待, 不同对象 A阻塞 B不受影响
7.A B 方法内添加 synchronized(SyncTest.class)
1 2 3 4 5 6 7 8 9 10 11 12 13
| class SyncTest { void methodA() { synchronized (SyncTest.class) { } } void methodB() { synchronized (SyncTest.class) { } }
}
|
结论: 同一/不同对象 A 阻塞 B等待
8.A 方法内添加 synchronized(SyncTest.class), B 方法内添加 synchronized(this)
1 2 3 4 5 6 7 8 9 10 11 12 13
| class SyncTest { void methodA() { synchronized (SyncTest.class) { } } void methodB() { synchronized (this) { } }
}
|
结论: 同一/不同对象 A 阻塞 B不受影响
9.A 方法内添加 synchronized(SyncTest.class), B 方法内添加 synchronized(OtherObj)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class SyncTest {
private String string = "lock";
void methodA() { synchronized (SyncTest.class) { } } void methodB() { synchronized (string) { } }
}
|
结论: 同一/不同对象 A 阻塞 B不受影响