如果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:一般字段:1232021-06-04 13:29:41:锁定一般办法2021-06-04 13:29:41:锁定动态变量2021-06-04 13:29:41:锁定一般变量2021-06-04 13:29:46:62021-06-04 13:29:46:22021-06-04 13:29:46:12021-06-04 13:29:46:42021-06-04 13:29:46:32021-06-04 13:29:46:52021-06-04 13:29:46:锁定静态方法2021-06-04 13:29:46:锁定一般对象2021-06-04 13:29:51:82021-06-04 13:29:51:7
重复尝试,发现可见锁静态方法会与锁class对象造成竞态条件,锁一般办法会与锁一般对象造成竞态条件
//todo