假設我有這個代碼塊:
List<Integer> lst = Collections.synchronizedCollection(new ArrayList<>());
我有以下兩種方法:
public Integer returnFirst() {
lst.get(0);
}
public void iterate() {
synchronized(lst) {
Iterator i = lst.iterator();
while (i.hasNext()) {
System.out.println(i);
}
}
}
假設一個執行緒呼叫 iterate(),然后另一個執行緒呼叫 returnFirst()。因為您在迭代中同步 List 物件,并且迭代當前正在運行,所以 returnFirst() 會被阻止嗎?
uj5u.com熱心網友回復:
是的,你是對的。 在完成returnFirst之前不會運行iterate。
uj5u.com熱心網友回復:
是的。看一下SynchronizedCollection建構式amdSynchronizedList#get方法:
SynchronizedCollection(Collection<E> c) {
this.c = Objects.requireNonNull(c);
mutex = this;
}
public E get(int index) {
synchronized (mutex) {return list.get(index);}
}
您可以看到用于控制并發訪問的內部互斥鎖實際上是物件本身(mutex = this),這意味著lst.get(0)和synchronized(LST)在您的iterate()方法中競爭相同的鎖:物件本身。
此外,您的代碼將無法編譯,替換synchronizedCollection為synchronizedList.
簡單代碼測驗:
public static void main(String[] args) throws InterruptedException {
List<Integer> list = Collections.synchronizedList(new ArrayList<>());
list.add(1);
new Thread(() -> {
try {
synchronized(list) {
Thread.sleep(5000);
Iterator i = list.iterator();
while (i.hasNext()) {
System.out.println(i.next());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
Thread.sleep(100);
new Thread(() -> {
// It will block for 5 seconds and then output
System.out.println(list.get(0));
}).start();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/327002.html
上一篇:創建執行緒時出現編譯時錯誤
