2012-06-30 48 views
12

同步我遇到類似於下面的代碼幾次與虛擬對象,而不是這個

class Foo { 
    private Object lock = new Object(); 

    public void doSomething() { 
     synchronized(lock) { 
     ... 

我很感興趣的是,爲什麼要創建,而不是寫synchronized(this)的鎖對象?是否有共享鎖?我依稀記得,這是一個優化。真的嗎?另外,在某些情況下,是否有理由將鎖聲明爲final

+0

這個問題是在這裏找到答案:http://stackoverflow.com/a/3369303/1343161 – Keppil

回答

23
  1. 同步上this是如果對象本身被用作從它會破壞內部同步外側的鎖,因爲氣餒。此外,請記住​​方法也使用this作爲鎖,這可能會導致不必要的影響。
  2. 建議聲明鎖final以防止在​​塊內重新分配鎖對象,從而導致不同的線程查看不同的鎖對象。看到這個的其他問題:Locking on a mutable object - Why is it considered a bad practice?
+0

+1;你值得擁有一個不錯的答案徽章:) – GETah

3

想象一下,你有thread1thread2訪問method1thread3thread4訪問method2的場景。同步上this會阻止thread3thread4如果thread1thread2正在訪問method1這不應該發生,因爲thread3thread4都無關method1。對此的優化是使用兩個不同的鎖而不是鎖定整個類實例。

這裏是一個不錯的段落我Javadoc的發現反映了這一點:

同步聲明也爲提高併發性 細粒度同步有用。例如,假設類MsLunch有兩個實例字段c1和c2,它們從不一起使用。這些領域的所有 更新必須是同步的,但沒有理由 防止C1的更新被交錯與C2的更新 - 和這樣通過製造不必要的阻擋

+0

+1也適合你。一個很好的例子,爲什麼鎖應該是細粒度的。 – Tudor

0

考慮使用鎖定會降低併發來自java.util.concurrent包
這可能會提供更多的優化鎖定,例如 - 使用ReadWriteLock將讓所有讀者無需等待即可訪問。

0

這是「ReentrantReadWriteLock」的完整示例。

public class DataReader { 
private static final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock(); 
private static final Lock read = readWriteLock.readLock(); 
private static final Lock write = readWriteLock.writeLock(); 
public static void loadData() { 
    try { 
    write.lock(); 
    loadDataFromTheDB()); 
    } finally { 
    write.unlock(); 
    } 
} 

public static boolean readData() { 
    try { 
    read.lock(); 
    readData(); 
    } finally { 
    read.unlock(); 
    } 
} 

public static List loadDataFromTheDB() { 
    List list = new ArrayList(); 
    return list; 
} 

    public static void readData() throws DataServicesException { 
    //Write reading logic 
    } 
}