在Java開發的時候經常會用到關鍵字synchronized來對代碼進行同步,在使用的過程中,對於synchronized確不是很熟悉,最近在看Spring源碼時,發現有不少地方都用到同步,因此,趁此機會,研究一下。
1. synchronized鎖的對象
Java中的每一個對象都可以作為鎖。
1)對於同步方法,鎖是當前實例對象。
2)對於靜態同步方法,鎖是當前對象的Class對象。因為在Java 虛擬機中一個類只能對應一個類對象,所以同時只允許一個線程執行同一個類中的靜態同步方法。
3)對於同步方法塊,鎖是Synchonized括號裡配置的對象。
下面我們將一一根據代碼來介紹這幾種鎖。
2. 同步實例方法
對於同步方法,鎖是當前實例對象。即在同一時刻只能有一個線程可以訪問該實例的同步方法。但是請注意,如果有多個實例對象,那麼不同示例之間不受影響,線程可以同時訪問不同示例的同步方法。看下面這段代碼:
package com.bj.chenfeic.concurrency;
/**
* 同步測試,提供了用於同步的實例方法
*
* @author chenfei0801
*
*/
public class Sync {
public synchronized void testSync() {
long id = Thread.currentThread().getId();
System.out.println("線程:" + id + "進入同步塊");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("線程:" + id + "退出同步塊");
}
}
package com.bj.chenfeic.concurrency;
/**
*
* @author chenfei0801
*
*/
public class SyncTread implements Runnable {
@Override
public void run() {
Sync sync = new Sync();
sync.testSync();
}
}
package com.bj.chenfeic.concurrency;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* @author chenfei0801
*
*/
public class SyncTest {
/**
* @param args
*/
public static void main(String[] args) {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(10);
for(int i=0;i<3;i++) {
newFixedThreadPool.execute(new SyncTread());
}
newFixedThreadPool.shutdown();
}
}
執行結果:
線程:11進入同步塊
線程:13進入同步塊
線程:12進入同步塊
線程:13退出同步塊
線程:11退出同步塊
線程:12退出同步塊
從執行結果中,我們可以看到testSync並沒有同步,synchronized沒有生效。這是因為在SyncTherd中每次都是new Sync();這樣synchronized其實是作用到不同的對象上去了,所以各個線程之間其實並沒有同步。
按照如下修改SynsThread、SyncTest代碼,即可達到同步作用
package com.bj.chenfeic.concurrency;
/**
*
* @author chenfei0801
*
*/
public class SyncTread implements Runnable {
private Sync sync;
public SyncTread(Sync sync) {
this.sync = sync;
}
@Override
public void run() {
this.sync.testSync();
}
}
package com.bj.chenfeic.concurrency;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* @author chenfei0801
*
*/
public class SyncTest {
/**
* @param args
*/
public static void main(String[] args) {
Sync sync = new Sync();//只實例化一次
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(10);
for (int i = 0; i < 3; i++) {
newFixedThreadPool.execute(new SyncTread(sync));
}
newFixedThreadPool.shutdown();
}
}
執行結果
線程:11進入同步塊
線程:11退出同步塊
線程:12進入同步塊
線程:12退出同步塊
線程:13進入同步塊
線程:13退出同步塊
從上面結果中可以看出,SyncThread中使用的是同一個對象,此時線程是互斥訪問testSync()方法的,即達到了同步的作用。
大話設計模式(帶目錄完整版) PDF+源代碼 http://www.linuxidc.com/Linux/2014-08/105152.htm
Java中介者設計模式 http://www.linuxidc.com/Linux/2014-07/104319.htm
Java 設計模式之模板方法開發中應用 http://www.linuxidc.com/Linux/2014-07/104318.htm
設計模式之 Java 中的單例模式(Singleton) http://www.linuxidc.com/Linux/2014-06/103542.htm
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2014-10/107579p2.htm