轉載自:http://hi.baidu.com/wojiubaibudu/blog/item/a27d671ed654cae6e1fe0b42.html
1.方法聲明時使用,放在範圍操作符(public等)之後,返回類型聲明(void等)之前.即一次只能有一個線程進入該方法,其他線程要想在此時調用該方法,只能排隊等候,當前線程(就是在synchronized方法內部的線程)執行完該方法後,別的線程才能進入.
- 例如:
- public synchronized void synMethod() {
- //方法體
- }
2.對某一代碼塊使用,synchronized後跟括號,括號裏是變量,這樣,一次只有一個線程進入該代碼塊.例如:
- public int synMethod(int a1){
- synchronized(a1) {
- //一次只能有一個線程進入
- }
- }
3.synchronized後面括號裏是一對象,此時,線程獲得的是對象鎖.例如:
- public class MyThread implements Runnable {
- public static void main(String args[]) {
- MyThread mt = new MyThread();
- Thread t1 = new Thread(mt, "t1");
- Thread t2 = new Thread(mt, "t2");
- Thread t3 = new Thread(mt, "t3");
- Thread t4 = new Thread(mt, "t4");
- Thread t5 = new Thread(mt, "t5");
- Thread t6 = new Thread(mt, "t6");
- t1.start();
- t2.start();
- t3.start();
- t4.start();
- t5.start();
- t6.start();
- }
- public void run() {
- synchronized (this) {
- System.out.println(Thread.currentThread().getName());
- }
- }
- }
對於3,如果線程進入,則得到對象鎖,那麼別的線程在該類所有對象上的任何操作都不能進行.在對象級使用鎖通常是一種比較粗糙的方法。爲什麼要將整個對象 都上鎖,而不允許其他線程短暫地使用對象中其他同步方法來訪問共享資源?如果一個對象擁有多個資源,就不需要只爲了讓一個線程使用其中一部分資源,就將所 有線程都鎖在外面。由於每個對象都有鎖,可以如下所示使用虛擬對象來上鎖:
- class FineGrainLock {
- MyMemberClass x, y;
- Object xlock = new Object(), ylock = new Object();
- public void foo() {
- synchronized(xlock) {
- //access x here
- }
- //do something here - but don‘t use shared resources
- synchronized(ylock) {
- //access y here
- }
- }
- public void bar() {
- synchronized(this) {
- //access both x and y here
- }
- //do something here - but don‘t use shared resources
- }
- }
4.synchronized後面括號裏是類.例如:
- class ArrayWithLockOrder{
- private static long num_locks = 0;
- private long lock_order;
- private int[] arr;
- public ArrayWithLockOrder(int[] a)
- {
- aarr = a;
- synchronized(ArrayWithLockOrder.class) {//-----------------------------------------這裏
- num_locks++; // 鎖數加 1。
- lock_order = num_locks; // 爲此對象實例設置唯一的 lock_order。
- }
- }
- public long lockOrder()
- {
- return lock_order;
- }
- public int[] array()
- {
- return arr;
- }
- }
- class SomeClass implements Runnable
- {
- public int sumArrays(ArrayWithLockOrder a1,
- ArrayWithLockOrder a2)
- {
- int value = 0;
- ArrayWithLockOrder first = a1; // 保留數組引用的一個
- ArrayWithLockOrder last = a2; // 本地副本。
- int size = a1.array().length;
- if (size == a2.array().length)
- {
- if (a1.lockOrder() > a2.lockOrder()) // 確定並設置對象的鎖定
- { // 順序。
- first = a2;
- last = a1;
- }
- synchronized(first) { // 按正確的順序鎖定對象。
- synchronized(last) {
- int[] arr1 = a1.array();
- int[] arr2 = a2.array();
- for (int i=0; i value += arr1[i] + arr2[i];
- }
- }
- }
- return value;
- }
- public void run() {
- //...
- }
- }
對於4,如果線程進入,則線程在該類中所有操作不能進行,包括靜態變量和靜態方法,實際上,對於含有靜態方法和靜態變量的代碼塊的同步,我們通常用4來加鎖.
以上4種之間的關係:
鎖 是和對象相關聯的,每個對象有一把鎖,爲了執行synchronized語句,線程必須能夠獲得synchronized語句中表達式指定的對象的鎖,一 個對象只有一把鎖,被一個線程獲得之後它就不再擁有這把鎖,線程在執行完synchronized語句後,將獲得鎖交還給對象。
在方法前面加上synchronized修飾符即可以將一個方法聲明爲同步化方法。同步化方法在執行之前獲得一個鎖。如果這是一個類方法,那麼獲得的鎖是和聲明方法的類相關的Class類對象的鎖。如果這是一個實例方法,那麼此鎖是this對象的鎖。