[英]Using 'this' versus another object as lock in synchronized block with wait and notify
我有兩個代碼塊,一個等待另一個通知它。
synchronized(this) {
wait();
}
和
while(condition) {
//do stuff
synchronized(this) {
notify();
}
}
奇怪的是,在這樣做時沒有等待通知:
synchronized(objectLock) {
objectLock.wait();
}
和
while(condition) {
//do stuff
synchronized(objectLock) {
objectLock.notify();
}
}
我對這兩組的差異非常好奇,為什么第一組有效,而另一組沒有。 請注意,這兩個塊位於兩個不同方法的兩個不同線程中(如果這有幫助)。
我希望有人可以解釋為什么會這樣。 我編輯了我的問題所以它會更加詳細。
您可以使用任何您喜歡的對象。 但是,其他程序員通常更清楚地看到顯式鎖對象。
我的胡亂猜測,為什么this
不適合你的工作是你有不同的this
范圍。 (即,在匿名函數/回調中)。 您可以通過附加類名來明確說明要使用哪個類,例如, WonderClass.this
- this
也是為什么this
不清楚的原因。 (編輯:實際上是WhateverClass.this
如果this
真的是一個不同的實例, this
對你沒有幫助)
另請閱讀: http : //docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html - 我通常會發現將所有線程不安全的代碼放入小型同步方法(執行隱含鎖定)更容易在此)
它沒有工作,因為你在同步this
這兩個不同的線程指出,兩個不同的 Thread
對象。
與wait()
和notify()
同步只有在同一個對象上進行同步鎖定時才能正常工作,就像稍后使用的objectLock
一樣。
編輯:如果兩個線程實例屬於同一個MyThread
類,那么為了達到您認為代碼所具有的效果,您必須獲取其類對象本身的鎖定:
synchronized(MyThread.class)
當你說這兩個塊存在於兩個不同的線程中時,我認為它們並沒有鎖定在同一個對象上,因為this
不是一回事。 當您命名一個顯式鎖定時,您使用相同的東西來鎖定。
順便說一下,你應該在循環中調用wait
,如下所示:
synchronized(someLock) {
while (!someCondition) {
wait();
}
// now the thread has the lock and it can do things
// knowing for sure that someCondition is true
}
如果沒有這個,您將容易受到虛假喚醒的攻擊(並非所有通知都來自您的應用程序代碼),並且調用wait
和notify
的順序會出現問題(如果您有兩個線程,並且在另一個等待之前通知,那么通知永遠不會被看到)。
無論如何,我建議使用Monitor模式( http://en.wikipedia.org/wiki/Monitor_(synchronization) ),這可以避免以后的錯誤,特別是當您的用例變得更復雜時:
class Monitor
{
/** Initialised to `false` by default in Java. */
boolean condition;
synchronized void waitForSomething()
{
while(!condition)
{
wait();
}
}
synchronized void signal()
{
condition = true;
notify();
}
}
這樣一切都很好地封裝和保護(我通常不會在示例中使用private
修飾符,但您可能希望在代碼中強制執行額外的“隱私”,特別是將condition
private
。)
正如你所看到的,在我的條件循環中有wait()
調用,而不是你在循環中有notify()
例子。 在大多數用例中,使用notify
做的事情是錯誤的,雖然我不能代表您的具體情況,因為您沒有向我們提供足夠的詳細信息。 我願意打賭你的是典型的,其中Monitor模式適用得很漂亮。
使用場景如下:想要等待某事的線程調用waitForSomething
而另一個線程可能通過調用將設置條件標志的signal
方法使其繼續。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.