2012-02-10 56 views
4

在我的課堂我有這樣的代碼:如何在java中提供2個變量的原子讀/寫?

int counter1; 
int counter2; 

public void method1(){ 
if (counter1>0) { 
    ...........do something 
    if (counter2>0) { 
    ....do something else 
    } 
} 

public void method2() { 
    counter1=0; 
    counter2=0; 
} 

我需要兩個計數器設置在一起。恐怕OS只能設置counter1後才能調用method1。這有可能嗎? 謝謝。

回答

4

要麼使用synchronized關鍵字作爲其他答案建議,要麼使用ReentrantReadWriteLock(如果讀取次數多於寫入計數器)以獲得更好的性能。您可以在這裏閱讀關於鎖的信息http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html

private int counter1; 
private int counter2; 
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); 
private final Lock r = rwl.readLock(); 
private final Lock w = rwl.writeLock(); 

public void method1(){ 
    r.lock(); 
    try { 
    if (counter1>0) { 
     ...........do something 
    if (counter2>0) { 
     ....do something else 
    } 
    } finally { r.unlock(); } 

} 

public void method2() { 
    w.lock(); 
    try { 
    counter1=0; 
    counter2=0; 
    } finally { w.unlock(); } 

} 
3

當然,只要使用synchronized關鍵字:

private final Object LOCK = new Object(); 
int counter1; 
int counter2; 

public void method1() { 
    synchronized(LOCK) { 
    if (counter1>0) { 
     ...........do something 
     if (counter2>0) { 
     ....do something else 
     } 
    } 
} 
public void method2() { 
    synchronized(LOCK) { 
    counter1=0; 
    counter2=0; 
    } 
} 

一些提示:

使用私有對象進行同步,而不是同步標記的方法。這可以防止你課堂外的某些東西抓住鎖並拖延事情。

請確保您在任何地方使用同步關鍵字,並確保您始終在同一個對象上進行同步。如果您忘記執行其中的任何一項,則兩個進程可以同時訪問這些字段。

小心死鎖。在完美的世界中,你會編寫單元測試來確保鎖定按照你認爲的方式工作。

+0

使用單元測試測試死鎖情況相當棘手。 – 2012-02-10 10:03:06

+0

是的。但這是可能的。一種方法是注入鎖,而不是使用synchronized關鍵字。 – 2012-02-10 10:05:02

+0

不明白,鎖定私人和方法之間有什麼區別?線程1可以調用方法1,線程2可以調用方法1,一個會被阻塞 - 兩種方法都沒有區別(方法和私有變量);我唯一能看到的是你想允許對班級中不同位數的數據進行不同的鎖定(這是合理的,但你必須知道你在做什麼......) - 然後我會爭辯說數據屬於不同的類 – Nim 2012-02-10 10:07:37

1

使用同步塊或方法來包裝對兩個計數器的訪問,請記住使用同一個對象進行鎖定。

相關問題