[英]Java synchronize on object
如何同步來自同一個類的兩個不同方法以鎖定同一個對象? 下面是一個例子:
public class MyClass extends Thread implements Observer{
public List<AnotherClass> myList = null;
public MyClass(List<AnotherClass> myList){
this.myList = myList;
}
public void run(){
while(true){
//Do some stuff
myList.add(NotImportantElement);
}
}
public void doJob{
for(int i=0; i<myList.size; i++){
ElementClass x = myList.get(i);
//Do some more stuff
}
}
}
問題是如何在執行 doJob 時阻止 run() 訪問 myList,反之亦然?
想象一下:我啟動線程並開始向我的列表添加元素。 在一個隨機時刻,我從另一個持有對我的線程的引用的類調用 doJob()。
我應該怎么做鎖? 謝謝!
樂
好的,我理解了鎖的概念,但現在我有另一個問題。
假設我有一個帶有public static myList
的類,並且只有該類的一個實例。 從那個實例中,我創建了n
個Thread
實例,它們獲取該列表的每個元素並用它做一些事情。
現在,在特定時刻更新myList
。 那些已經在處理 myList 元素的線程會發生什么? 我應該如何在更新myList
時鎖定myList
訪問?
注意:此代碼假定您只有一個 MyClass 實例。 根據你的帖子,聽起來是這樣。
public class MyClass extends Thread implements Observer{
private List<AnotherClass> myList = null;
private Object lock = new Object();
public MyClass(List<AnotherClass> myList){
this.myList = new ArrayList(myList);
}
public void run(){
while(true){
//Do some stuff
synchronized(lock) {
myList.add(NotImportantElement);
}
}
}
public void doJob{
synchronized(lock) {
for(int i=0; i<myList.size; i++){
ElementClass x = myList.get(i);
//Do some more stuff
}
}
}
}
編輯:添加了制作 List 的副本,以便外部實體無法按照 JB Nizet 更改列表
編輯 2:將變量設為私有,以便其他人無法訪問它們
你可以:
run
和doJob
synchronized
。 這將使用this
作為鎖;final
列表並對其進行同步。 這將使用列表作為鎖。 將鎖定字段聲明為final
是一種很好的做法。 這樣,您的類的某些方法可以在一個對象上同步,而其他方法可以使用其他對象進行同步。 這減少了鎖爭用,但增加了代碼復雜性;java.util.concurrent.locks.Lock
變量並使用它的方法進行同步。 這將提高代碼的靈活性,但也會增加代碼的復雜性;BlockingQueue
或CopyOnWriteArrayList
。 這將降低代碼復雜度並確保線程安全。volatile
字段來實現同步。 請參閱此SO 帖子。 這將確保安全,但會大大增加復雜性。 第二個想法,不要這樣做:)您可以添加
同步
兩種方法的關鍵字或使用
synchronized(Myclass.class) {
}
前者本質上使用 Myclass.class 對象,但它不像后者那樣細粒度。
將這兩種方法聲明為synchronized
以鎖定每個實例,或者使用synchronized(this){...}
塊只鎖定當前實例。
synchronized(myList) {
// do stuff on myList
}
具體文檔: Intrinsic Locks and Synchronization
然而,我鼓勵您使用線程安全的並發數據結構來實現您想要實現的目標,以避免同步並獲得(很多)更好的性能:並發包摘要
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.