【問題描述】關于Java中synchronized 用在執行個體方法和對象方法上面的差別
【問題分析】大家都知道,在Java中,synchronized 是用來表示同步的,我們可以synchronized 來修飾一個方法(執行個體方法和類方法---注:不知道這樣叫準确不準确,大家了解我的意識就行了)。也可以synchronized 來修飾方法裡面的一個語句塊。
修飾執行個體方法:
public synchronized void x() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("x......................."); } }
修飾類方法(static 方法):public static synchronized void staticX() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("staticX......................."); } }
修飾方法裡面語句塊:public static void staticX() throws InterruptedException { synchronized (locks) { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("staticX......................."); } } }
注意:這裡不能用synchronized修飾方法外面的語句塊(我把他叫做類語句塊),雖然我們可以在方法外面定義語句塊,這樣做會遇到編譯錯誤,這裡涉及到了Java裡面的對象初始化的部分知識。大概的原因就是synchronized鎖住的是對象,當初始化對象的時候,JVM在對象初始化完成之前會調用方法外面的語句塊,這個時候對象還不存在,是以就不存在鎖了。
那麼,在static方法和非static方法前面加synchronized到底有什麼不同呢?
大家都知道,static的方法屬于類方法,它屬于這個Class(注意:這裡的Class不是指Class的某個具體對象),那麼static擷取到的鎖,就是目前調用這個方法的對象所屬的類(Class,而不再是由這個Class産生的某個具體對象了)。而非static方法擷取到的鎖,就是目前調用這個方法的對象的鎖了。是以,他們之間不會産生互斥。
看代碼:
package com.jack.zhang.chapter9.classlock; public class Test { public static synchronized void staticX() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("staticX......................."); } } public synchronized void x() throws InterruptedException { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("x......................."); } } public static void main(String[] args) { final Test test1 = new Test(); Thread thread = new Thread(new Runnable() { public void run() { try { test1.x(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }, "a"); Thread thread1 = new Thread(new Runnable() { public void run() { try { Test.staticX(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }, "b"); thread1.start(); thread.start(); } }
運作結果是:
staticX....................... x....................... x....................... staticX....................... staticX....................... x....................... x....................... staticX....................... x....................... staticX....................... staticX....................... x....................... x....................... staticX....................... x....................... staticX....................... x....................... staticX....................... x....................... staticX.......................
那當我們想讓所有這個類下面的對象都同步的時候,也就是讓所有這個類下面的對象共用同一把鎖的時候,我們如何辦呢?
看代碼:
package com.jack.zhang.chapter9.classlock; public class Test { public final static Byte[] locks = new Byte[0]; public static void staticX() throws InterruptedException { synchronized (locks) { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("staticX......................."); } } } public void x() throws InterruptedException { synchronized (locks) { for (int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("x......................."); } } } public static void main(String[] args) { final Test test1 = new Test(); final Test test2 = new Test(); Thread thread = new Thread(new Runnable() { public void run() { try { test1.x(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }, "a"); Thread thread1 = new Thread(new Runnable() { public void run() { try { Test.staticX(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }, "b"); thread1.start(); thread.start(); } }
運作結果:
staticX....................... staticX....................... staticX....................... staticX....................... staticX....................... staticX....................... staticX....................... staticX....................... staticX....................... staticX....................... x....................... x....................... x....................... x....................... x....................... x....................... x....................... x....................... x....................... x.......................