2010-10-28 56 views
14

在高度併發的系統中,可能很難確信您的鎖的使用是正確的。具體而言,如果在另一個線程中以正確的順序獲取鎖而獲取的順序不是預期的順序,則會導致死鎖。在Java中聲明同步的順序

有一些工具(例如Coverity)可以在代碼庫上進行靜態分析並尋找「異常」的鎖定順序。我想探索其他選擇來滿足我的需求。

是否有任何輕量級*工具可用於檢測Java代碼,這些工具可以檢測到以預期以外的順序獲取鎖的情況?我可以通過註釋/註釋顯式調用鎖定命令。

首選免費和/或開源解決方案。請同時評論這個問題是否存在非儀器方法。

*對於我而言,重量輕是指...

  • 如果是儀表,我仍然可以使用相同的球場性能運行我的程序。我想,30-50%的降解是可以接受的。
  • 我不必花半天的時間與工具進行交互,只是爲了獲得「好的」。理想情況下,我應該只注意到在出現問題時我正在使用它。
  • 如果是儀表,應該很容易在生產環境中禁用。
  • 它不應該在每個synchronize聲明中混淆我的代碼。如前所述,我可以明確地評論/註釋被相對排序鎖定的對象或類的對象。
+1

...這就是爲什麼Actor模型和STM越來越流行 – 2010-10-28 20:32:34

+0

有人有一個引用java.lang.Thread.holdsLock(Object)的響應被及時刪除。我無法自己找到這種方法,謝謝你的指點。不過,我的問題依然存在。 – 2010-10-28 20:48:37

+0

你有沒有發現任何像樣的事情?我在C++中有非常複雜的死鎖檢測代碼,在我的情況下,我想用我們的Java代碼來捕獲在C++和/或java端的鎖可能會相互干擾並導致死鎖的情況。 – Pavel 2015-01-27 02:32:35

回答

3

我還沒有使用過AspectJ,因此無法證明它使用起來有多容易。我用ASM來創建一個自定義的代碼分析器,這是大約2天的工作。儀器同步的努力應該類似。 AspectJ應該更快,更容易,一旦你加快了方面。

我已經爲我們基於C++的服務器實現了死鎖檢測跟蹤。這是我如何做的:

  • 當曾經獲得或釋放鎖我跟蹤:
    • <time> <tid> <lockid> <acquiring|releasing> <location in code>
  • 這額外的跟蹤性能的影響非常顯着,是不是在生產中使用。
  • 因此,當在生產中發現可能的死鎖時,我使用日誌文件找出死鎖周圍發生的事情。然後在打開跟蹤的情況下在測試環境中再現此功能。
  • 然後我在日誌文件上運行了一個腳本來查看死鎖是否可行以及如何。我用awk腳本,使用這種algoritm:
    • FOREACH線
      • 如果獲取
        • 添加lockid到當前鎖的列表此線程
        • 在此列表中添加每對鎖的一組爲此線程鎖定對。例如用於Lock A -> Lock B -> Lock C列表生成對(Lock A, Lock B), (Lock A, Lock C), (Lock B, Lock C)
      • 只要解除
        • 從列表的尾部刪除當前lockid該線程
    • 對於每個鎖對搜索所有其他線程的反向鎖對,每個匹配是一個潛在的死鎖,因此打印受影響的線對和線程
    • 而不是讓算法更聰明我然後桌子檢查,第鎖定獲取以查看它是否是真正的死鎖。

我沒有找到多天的僵局的原因後這樣做,花了幾天時間來實施並在幾個小時找到了僵局。

如果你正在考慮在Java的東西,這個辦法要考慮的是:

  • 你只使用​​,保護重要的部分?你在使用java.lang.concurrent中的類嗎? (這些可能需要特殊處理/儀器)
  • 使用aspect/ASM打印代碼位置有多容易?我在C++中使用了__FILE____LINE__。 ASM會給你類名,方法名和簽名。
  • 您無法檢測用於保護跟蹤/記錄的鎖。
  • 如果您使用每個線程的日誌文件和文件對象的線程本地存儲,則可以簡化您的檢測。
  • 你如何唯一標識你同步的對象?也許toString()和System.identityHashCode()就足夠了,但可能需要更多。我用C++中的對象地址。
+0

這是一個合理的解決方案,但我希望有一個工具可以爲我完成所有這些工作。將更多地考慮ASM - 謝謝。 – 2010-10-29 13:08:56

0

沒有得到你一路有,但一個良好的開端是使用JCIP annotations,並FindBugs抓住一些東西。

+0

除非我遺漏了一些東西,FindBugs沒有對顯示器(同步塊)排序進行任何檢查。 – 2010-10-29 13:01:51

+0

@德里克·賴斯:我沒有意識到有任何工具可以完成OQ所要求的工作,但在附近提供了一些東西...... – andersoj 2010-10-29 16:17:05

1

您可以使用AspectJ,這是相對容易學習,並允許您設置自己的自定義和簡化的方式來監視您的線程和他們訪問的任何鎖。

+1

謝謝。我遵循這個想法,直到我得到這篇文章「AspectJ中同步塊的加入點」:http://www.cs.man.ac.uk/~xic/SBJP_AspectJ.pdf – 2010-10-29 12:55:55

+0

不錯的論文。感謝分享鏈接,如果這些缺點不能在您的情況下使用,感謝抱歉。 – 2010-10-31 01:26:42