如果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对象形成竞态条件,锁普通方法会与锁普通对象形成竞态条件
Synchronized原理:
synchronized的底层依赖于Monitor对象,即管程控制对象并发访问机制的具体实现
1.对象内存布局
hotspot虚拟机中,对象内存分为三块区域:
- 对象头(Header)
- 实例数据(Instance Data)
- 对齐填充(padding)
1.1 对象头Header
header主要包含markword和对象指针KlassPointer,如果是数组的话,还包含数组的长度
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。