共计 4065 个字符,预计需要花费 11 分钟才能阅读完成。
如果 synchronized 锁住一个对象的不同变量或办法, 会造成竞态条件吗?synchronized 背地的原理是什么?
先看一个试验:
// 别离尝试去锁一个对象的成员变量, 成员办法, 动态变量, 静态方法, | |
//class 对象以及对象自身, 哪些操作会造成动态条件? | |
public class TestObj { | |
private String field1 = "123"; | |
private static String field2 = "456"; | |
private String field3; | |
private String field4; | |
public void normalMethod() {Date date = new Date(); | |
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
String time = format.format(date); | |
System.out.println(time+": 一般办法"); | |
try {Thread.sleep(5000); | |
System.out.println(format.format(new Date())+":"+Thread.currentThread().getName()); | |
} catch (InterruptedException e) {e.printStackTrace(); | |
} | |
} | |
public synchronized void lockMethod() {Date date = new Date(); | |
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
String time = format.format(date); | |
System.out.println(time+": 锁定一般办法"); | |
try {Thread.sleep(5000); | |
System.out.println(format.format(new Date())+":"+Thread.currentThread().getName()); | |
} catch (InterruptedException e) {e.printStackTrace(); | |
} | |
} | |
public static synchronized void lockStaticMethod() {Date date = new Date(); | |
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
String time = format.format(date); | |
System.out.println(time+": 锁定静态方法"); | |
try {Thread.sleep(5000); | |
System.out.println(format.format(new Date())+":"+Thread.currentThread().getName()); | |
} catch (InterruptedException e) {e.printStackTrace(); | |
} | |
} | |
public void lockField() {synchronized (field1) {Date date = new Date(); | |
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
String time = format.format(date); | |
System.out.println(time+": 锁定一般变量"); | |
try {Thread.sleep(5000); | |
System.out.println(format.format(new Date())+":"+Thread.currentThread().getName()); | |
} catch (InterruptedException e) {e.printStackTrace(); | |
} | |
} | |
} | |
public void lockStaticField() {synchronized (field2) {Date date = new Date(); | |
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
String time = format.format(date); | |
System.out.println(time+": 锁定动态变量"); | |
try {Thread.sleep(5000); | |
System.out.println(format.format(new Date())+":"+Thread.currentThread().getName()); | |
} catch (InterruptedException e) {e.printStackTrace(); | |
} | |
} | |
} | |
public void lockStaticClass() {synchronized (TestObj.class) {Date date = new Date(); | |
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
String time = format.format(date); | |
System.out.println(time+": 锁定 class 对象"); | |
try {Thread.sleep(5000); | |
System.out.println(format.format(new Date())+":"+Thread.currentThread().getName()); | |
} catch (InterruptedException e) {e.printStackTrace(); | |
} | |
} | |
} | |
public void normalField() {Date date = new Date(); | |
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
String time = format.format(date); | |
System.out.println(time+": 一般字段:"+field1); | |
try {Thread.sleep(5000); | |
System.out.println(format.format(new Date())+":"+Thread.currentThread().getName()); | |
} catch (InterruptedException e) {e.printStackTrace(); | |
} | |
} | |
} |
public class Main {public static void main(String[] args) {TestObj obj = new TestObj(); | |
Thread thread1 = new Thread(() -> {obj.lockStaticField(); | |
}, "1"); | |
Thread thread2 = new Thread(() -> {obj.lockStaticClass(); | |
}, "2"); | |
Thread thread8 = new Thread(() -> {TestObj.lockStaticMethod(); | |
}, "8"); | |
Thread thread3 = new Thread(() -> {obj.lockMethod(); | |
}, "3"); | |
Thread thread4 = new Thread(() -> {obj.lockField(); | |
}, "4"); | |
Thread thread5 = new Thread(() -> {obj.normalMethod(); | |
}, "5"); | |
Thread thread6 = new Thread(() -> {obj.normalField(); | |
}, "6"); | |
Thread thread7 = new Thread(() -> {synchronized (obj) {Date date = new Date(); | |
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
String time = format.format(date); | |
System.out.println(time + ": 锁定一般对象"); | |
try {Thread.sleep(5000); | |
System.out.println(format.format(new Date()) + ":" + Thread.currentThread().getName()); | |
} catch (InterruptedException e) {e.printStackTrace(); | |
} | |
} | |
}, "7"); | |
thread1.start(); | |
thread2.start(); | |
thread3.start(); | |
thread4.start(); | |
thread5.start(); | |
thread6.start(); | |
thread7.start(); | |
thread8.start();} | |
} |
颁布答案:
2021-06-04 13:29:41: 锁定 class 对象 | |
2021-06-04 13:29:41: 一般办法 | |
2021-06-04 13:29:41: 一般字段:123 | |
2021-06-04 13:29:41: 锁定一般办法 | |
2021-06-04 13:29:41: 锁定动态变量 | |
2021-06-04 13:29:41: 锁定一般变量 | |
2021-06-04 13:29:46:6 | |
2021-06-04 13:29:46:2 | |
2021-06-04 13:29:46:1 | |
2021-06-04 13:29:46:4 | |
2021-06-04 13:29:46:3 | |
2021-06-04 13:29:46:5 | |
2021-06-04 13:29:46: 锁定静态方法 | |
2021-06-04 13:29:46: 锁定一般对象 | |
2021-06-04 13:29:51:8 | |
2021-06-04 13:29:51:7 |
重复尝试, 发现可见 锁静态方法会与锁 class 对象造成竞态条件, 锁一般办法会与锁一般对象造成竞态条件
//todo
正文完