我有兩個數組,我需要跨線程同步對它們的訪問。我將把它們放在同步塊中。問題是,我只能通過其中一個來「同步」一次。java同步塊的超過1個對象?
如何確保對兩個陣列的訪問都是同步的? 我把它們放在課堂上並創建它的一個對象嗎? 或者我只在同步塊中訪問另一個數組,並且這需要同步對它的訪問嗎?
感謝,
我有兩個數組,我需要跨線程同步對它們的訪問。我將把它們放在同步塊中。問題是,我只能通過其中一個來「同步」一次。java同步塊的超過1個對象?
如何確保對兩個陣列的訪問都是同步的? 我把它們放在課堂上並創建它的一個對象嗎? 或者我只在同步塊中訪問另一個數組,並且這需要同步對它的訪問嗎?
感謝,
不管你做什麼不做到這一點:
synchronized (array1) {
synchronized (array2) {
// do stuff
}
}
這可能導致deadlock除非你非常小心。如果你採用這種方法,你必須確保你對物體有一個不變的部分順序 - 谷歌「餐飲哲學家」討論這些陷阱。
基本上你所要做的是創造,如果你想訪問要麼數組,你將使用,然後利用它來進行所有數組訪問一個鎖定對象。它粗粒,但安全。如果你需要,你要使用Java 5+等併發公用事業ReadWriteLock
更細粒度的方法,但是這將是更加複雜的實現,而且容易出錯
public static class TwoArrays {
private int[] array1 = ...
private int[] array2 = ...
private final Object LOCK = new Object();
public void doUpdate() {
synchronized (LOCK) {
...
}
}
}
:你可以這樣來做。
然後,你可以使'doUpdate'同步,而不是增加'LOCK'對象的複雜性。 – skaffman 2009-12-05 08:26:31
其實不是,最好不要暴露你的鎖,這是你在做鎖的時候所做的。 – cletus 2009-12-05 08:30:10
這會產生一個問題 - 如果在同一對象上存在另一個同步,則使用嵌套同步塊可能會導致死鎖。但是隻有上面的代碼存在纔會發生嗎?如果沒有數組的監視器,則線程無法獲取array2的監視器。如果它具有array1的監視器,則其他線程不能擁有array2的監視器。我的推理有沒有漏洞? – Bozho 2009-12-05 08:52:48
到Java 5之前,我已經寫了這樣的事情:
// pre Java 5 code:
Object lock = new Object();
// ...
synchronized(lock) {
// do something that requires synchronized access
}
但自從Java 5中,我會使用類從java.util.concurrent.locks
(個人而言,我不覺得這是更復雜或錯誤易發):
// Java 5 Code Using Locks
Lock lock = // ...
lock.lock();
try {
// do something that requires synchronized access
}
finally {
lock.unlock();
}
如果你需要讀寫鎖,我這裏是使用讀寫鎖從Java 5中實現:
private ReadWriteLock rwl = new ReentrantReadWriteLock();
private Lock rLock = rwl.readLock();
private Lock wLock = rwl.writeLock();
private List<String> data = new ArrayList<String>();
public String getData(int index) {
rLock.lock();
try {
return data.get(index);
} finally {
rLock.unlock();
}
}
public void addData(int index, String element) {
wLock.lock();
try {
data.add(index, element);
} finally {
wLock.unlock();
}
}
當然,適應它來滿足您的需求。
把他們放在一個新班級可能有助於澄清你想要做什麼,所以我會建議。但是,這根本不影響線程安全性。我喜歡使用顯式鎖定的答案(如下)。 – 2009-12-05 13:47:54