[英]What is the purpose of declaring a method synchronized in the following example
[英]What is the purpose of the following synchronized block?
我在使用OpenCMS時遇到了穩定性問題。 當我進行線程轉儲時,許多線程(400)正在等待以下代碼中的synchronized (m_processingFiles)
塊:
public class CmsJspLoader ... {
...
private static Set m_processingFiles = Collections.synchronizedSet(new HashSet());
...
...
...
public String updateJsp(...) {
....
while (m_processingFiles.contains(jspVfsName)) {
// wait a little bit until the first thread finishes
try {
synchronized (m_processingFiles) {
m_processingFiles.wait(100);
}
} catch (InterruptedException e) {
// ignore
}
}
...
}
...
}
該代碼是OpenCMS的一部分。 代碼中的任何地方都沒有notify()
。 在顯示的sync
塊內沒有狀態變化或讀取共享變量。 但是,有400個線程在等待它,這意味着,只是為了通過這個sync
,最后一個應該等待40秒!
我根本就不明白它的目的。 有什么我沒看到的嗎?
如果沒有notify或notifyAll調用,這將基本上像100ms睡眠一樣。 在100ms之后,線程將喚醒並繼續。 假設在同步塊內只有等待,那么這只是一種奇怪的睡眠方式。 同步塊觸發內存屏障可能會導致其他一些影響。 所以可能會出現一些微妙的線程安全事件。
在解釋線程轉儲時要注意的一件事是400個線程被阻塞等待進入同步塊或等待等待? 當線程進入等待時,它基本上從同步塊釋放鎖,以便另一個線程可以輸入它。 當線程從等待中醒來時,將重新獲取鎖定。
如果線程轉儲說“等待監視器條目”,那么一個線程在同步塊中,而其他所有線程都試圖進入。 這表明你有一個主要的並發問題。
但是,如果線程轉儲顯示類似“在Object.wait()”中的內容,則表示線程處於100ms等待狀態,其他線程可以自由進入同步塊。 在這種情況下,這意味着循環條件仍然是假的,所以看看那邊發生了什么,而不是等待線程發生了什么。
也就是說,如果可以執行notify / notifyAll,那么無論進程的另一端是什么,它都會減少延遲和喚醒成本以及檢查線程是否仍然處於休眠狀態。
必須有在一個線程添加一些代碼的地方jspVfsName
到m_processingFiles
,做一些更多的工作,然后刪除jspVfsName
從m_processingFiles
。 如果不是這種情況,那么你的其他線程就會在while
循環中永遠wait()
。 出於某種原因,實現者不希望任何其他線程在執行其他處理時執行updateJsp
。
我建議您檢查代碼以查看jspVfsName
實際上是什么,並找到代碼中可以從m_processingFiles
添加/刪除的m_processingFiles
。 或許,那么你也就會明白為什么筆者不想updateJsp
運行而jspVfsName
是m_processingFiles
。
一旦你發現,你可以檢查,“其他”代碼,看是否jspVfsName
能否被添加到m_processingFiles
和永遠不會被刪除 。 如果是這樣,那(自然)會導致活鎖,這可以解釋你的穩定性問題。
或者可能是非常頻繁地調用updateJsp
,並且還經常調用修改m_processingFiles
的“其他”代碼,以至於它會導致嚴重的並發瓶頸? 您的應用程序是否有問題導致updateJsp
被調用的頻率超過應有的頻率(可能在每個請求上,而不是每次在服務器上放置新的JSP文件時)?
如果updateJsp
非常頻繁地運行,但它不是由您的應用程序問題引起的,您可以嘗試簡單地縮短wait()
時間。 這不應該傷害任何東西 - 它只會使等待的線程檢查jspVfsName
是否仍然更頻繁地在m_processingFiles
。 在CPU方面, 100ms是一個漫長的時間!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.