關於線程的同步,可使用synchronized關鍵字,或者是使用JDK 5中提供的java.util.concurrent.lock包中的Lock對象。本文探討synchronized關鍵字。java
synchronized關鍵字能夠修飾方法,能夠修飾代碼塊,但不能修飾構造器、屬性等。併發
package com.clzhang.sample.thread; public class SyncThread1 implements Runnable { private Integer key = 0; @Override public void run() { // key是Integer對象(注意不是int,由於int不是對象) // 線程進入下面同步代碼以前,須要先獲取key的鎖。 // 須要結果是key實現自增加,若是沒有同步塊,則可能會出現重複key值的現象 synchronized (key) { key++; System.out.println(Thread.currentThread().getName() + ":" + key); try { Thread.sleep(100); } catch (InterruptedException e) { } } } public static void main(String[] args) { SyncThread1 st = new SyncThread1(); for(int i=0; i<10; i++) { new Thread(st, "Thread" + i).start(); } } }
輸出:ide
Thread1:2
Thread3:3
Thread5:4
Thread7:5
Thread0:2
Thread2:7
Thread9:6
Thread4:8
Thread6:9
Thread8:10this
同步方法分靜態和非靜態兩種。靜態方法則必定會同步,非靜態方法需在單例模式才生效,推薦用靜態方法(不用擔憂是否單例)。spa
package com.clzhang.sample.thread; // 若是是同步方法,則分靜態和非靜態兩種。 // 靜態方法則必定會同步,非靜態方法需在單例模式才生效,推薦用靜態方法(不用擔憂是否單例)。 public class SyncThread2 implements Runnable { private Integer key = 0; // 此示範爲非靜態方法同步 public synchronized Integer getKey() { key++; return key; } @Override public void run() { System.out.println(Thread.currentThread().getName() + ":" + getKey()); try { Thread.sleep(10); } catch (InterruptedException e) { } } public static void main(String[] args) { // 非靜態方法同步,須要啓動單例模式 SyncThread2 st = new SyncThread2(); for (int i = 0; i < 10; i++) { new Thread(st, "Thread" + i).start(); } } }
輸出:線程
Thread0:1
Thread1:3
Thread2:2
Thread3:5
Thread5:6
Thread7:7
Thread9:8
Thread6:9
Thread8:10
Thread4:4code
package com.clzhang.sample.thread; // 若是是同步方法,則分靜態和非靜態兩種。 // 靜態方法則必定會同步,非靜態方法需在單例模式才生效,推薦用靜態方法(不用擔憂是否單例)。 public class SyncThread3 implements Runnable { private static Integer key = 0; // 此示範爲靜態方法同步 public synchronized static Integer getKey() { key++; return key; } @Override public void run() { System.out.println(Thread.currentThread().getName() + ":" + getKey()); try { Thread.sleep(10); } catch (InterruptedException e) { } } public static void main(String[] args) { // 若是用靜態方法實現同步,則能夠生成對象的多個實例 for (int i = 0; i < 10; i++) { SyncThread3 st = new SyncThread3(); new Thread(st, "Thread" + i).start(); } } }
輸出:對象
Thread3:3
Thread1:1
Thread0:2
Thread5:4
Thread7:5
Thread9:6
Thread2:7
Thread8:10
Thread6:9
Thread4:8blog
一、不管是同步代碼塊仍是同步方法,必須得到對象鎖纔可以進入同步代碼塊或者同步方法進行操做。get
二、若是採用方法級別的同步,對象鎖爲方法所在的對象;若是是靜態同步方法,對象鎖爲方法所在的類(惟一)。
三、對於代碼塊,對象鎖即指synchronized(object)中的object。