2009-08-31 30 views
0

使用情況實例同步上的實習字符串

  • 我正在接收的登錄請求的servlet。
  • 如果當前正在登錄,或者用戶已經登錄,則該servlet應該中止並通知呼叫者。

當前設計

從數據庫拆分取得靈感,我打算使用每個用戶ID的第一個字符作爲同步密鑰。

void login(String userid) 
{ 
    String first = userid.substring(0, 1); 
    synchronized(first.intern()) 
    { 
    // query the cache or database for a session token. 
    // if session token exists, throw an exception 
    } 
} 

問題

  1. 據我所知,使用字符串#實習生可能溢出PermGen的空間。在我的情況下,被轉儲到permgen的字符串是一個Unicode字符。我是否安全地使用這樣的字符串?

回答

1

對於你的問題:彼爾姆應該能夠用一個字符編碼65536 String s(應該只有幾個兆字節)。

但是:

  • 這顯然不打算在多進程系統的工作。
  • 您運行死鎖的風險(如果某些其他代碼正在同步String s)。
  • 這真的很醜。
  • 真的你想要一個適當的節流(!),這應該不是很難。
+0

它如何在多處理器機器中不起作用?假設只有一個JVM。如果我使用自己的鎖,它與使用實體字符串(在多處理器機器中)有什麼不同? – 2009-08-31 08:43:32

+1

他沒有說這不適用於多處理器機器。它不適用於多進程系統,即運行多個JVM實例的系統(無論是在單臺計算機上還是在多臺計算機上) - 'synchronized'在JVM之間不起作用。 – Jesper 2009-08-31 12:12:46

+0

謝謝。我認爲這是一個錯字。 – 2009-08-31 13:37:15

1

PermGen溢出不是問題。但是:

  1. String.intern()是一個重量級操作,因爲它需要鎖定字符串常量池。這會降低吞吐量;
  2. 更重要的是,您將同步「逃離」您的控制對象,例如如果你使用庫有

    synchronized ("a") { 
        // do stuff 
    } 
    

塊地方,你會死鎖而不自知。它與BooleanInteger值的同步問題差不多。我建議你爲此使用自己的鎖。

+0

謝謝。我正在將我的設計遷移到使用自定義鎖的過程中。 – 2009-08-31 08:44:05

+0

'intern'在某種意義上是重量級的,但是當你談論使用數據庫連接等等時,它是相當小的。 – 2009-08-31 20:28:35