使用線程中的同步
回答
在已經給出的其他優秀答案中沒有提到的一件事是Code1和Code2之間的區別。在code1中,同步位於找到代碼的對象的實例上,而在code2中,它位於對象內的特定鎖對象上。
如果只有在外部類的兩個同步塊,還有的兩者之間沒有功能差異,但考慮到這一點:
class CodeOneClass { ... synchronized(this) { // or merely "synchronized" - it defaults to this first protected code block } ... synchronized(this) { second protected code block } ... } class CodeTwoClass { ... Object lock1 = new Object(); synchronized(lock1) { first protected code block } ... Object lock2 = new Object(); synchronized(lock2) { second protected code block } ... }
如果兩個線程試圖使用CodeOneClass的同一個實例,其中只有一個可以同時在兩個受保護的代碼塊中的任一個中。
但是有了第二個習慣用法,您可以靈活地說,一個線程處於第一個保護區,另一個處於另一個線程中是安全的。請注意,如果鎖相同(在同一個鎖對象上同步),則行爲將作爲第一個鎖。
還有其他的區別。一些作家開始用同步(這)指出的問題 - 我想指出你另一篇文章在這裏SO: Avoid synchronized(this) in Java?
我強烈建議你閱讀它,和三個職位它鏈接到。
基本上,Java中的每個對象都有一個「鎖」。
當一個線程到達一個調用synchronized(something)的地方時,它必須在繼續之前獲取某個東西的鎖。如果你想一次只允許一個線程修改對象的狀態,最明顯的是同步該對象的鎖定。如果允許不同的方法被並行調用,那麼你需要不同的鎖。
如果你寫同步(this),或者只是同步,線程必須獲取與當前對象(調用哪個方法)相關的鎖。
請注意,自Java 5.0以來,併發包提供了可用於代替同步的正確locks。
您能否提供一些示例或鏈接以進一步理解該主題,謝謝! – 2009-08-30 15:25:56
你讀過這個嗎? http://java.sun.com/docs/books/tutorial/essential/concurrency – Zed 2009-08-30 15:28:42
我會,現在!謝謝! – 2009-08-30 15:31:48
將代碼放在塊中本質上意味着「一旦此代碼開始運行,其他需要使用此對象的代碼不能同時運行。」
所以,如果線程#2是你的code2
塊執行的代碼,當涉及到synchronized(lock)
代碼它有效地環顧四周,在所有其他線程,以確保沒有其他正在運行「同步」的代碼與lock
目前的對象。線程#1肯定同時運行一些的代碼,但它可能是完全無關的代碼。如果是這樣,第二線程開始運行你的「some code
」是安全的。同時,如果線程#1到達synchronized(this)
塊,它也必須暫停並查看是否有任何其他線程正在使用this
。如果this
與lock
是同一個對象,則說明存在問題。我們被告知只有一個線程可能同時使用該對象(在同步塊中)。然而,線程#2已經在使用它。線程#1將不得不等待......並等待......並等待......直到最終線程#2完成。然後我們可以繼續。
最終的結果是,一次只能運行一個塊(當然有特定的對象)。
很好解釋! – 2009-08-30 15:39:06
假設你有一個Account
對象,它有一個方法:
void debit(long debitAmount, Account beneficiary) throws InsufficientFundsException
{
if (accountBalance >= debitAmount) {
accountBalance -= debitAmount;
beneficiary.credit(debitAmount);
}
else {
throw new InsufficientFundsException();
}
}
現在,假設你有100歐元的餘額帳戶,你會得到兩次嘗試了70歐元借記它。如果兩個借方發生在同一時間,你可以得到一個競爭條件這樣的:
- 首先借記支票賬戶餘額:100> = 70,所以成功
- 二借記支票賬戶餘額:100 > = 70,所以成功
- 第一次借記執行;賬戶餘額變爲30
- 第二次借記執行;賬戶餘額變爲-40。 不應該被允許
我們可以通過對Account
對象的鎖同步預防事務的這種可怕的狀態:
void debit(long debitAmount, Account beneficiary) throws InsufficientFundsException
{
synchronized (this) {
if (accountBalance >= debitAmount) {
accountBalance -= debitAmount;
beneficiary.credit(debitAmount);
}
else {
throw new InsufficientFundsException();
}
}
}
這可以確保在賬戶餘額的測試和借記能不會因帳戶餘額的另一項測試而中斷。
Sun Java tutorial是開始獲取併發和鎖定信息的好地方。
- 1. 使用WINAPI同步線程
- 2. 同步線程中的同步問題
- 3. Lisp中的線程同步
- 4. qt中的線程同步
- 5. C#中的線程同步?
- 6. Python中的線程同步
- 7. WinCE中的線程同步
- 8. java中的線程/同步
- 9. Django中的線程同步
- 10. 線程同步
- 11. 線程同步
- 12. 線程同步
- 13. 線程同步
- 14. 線程/同步
- 15. 線程同步
- 16. 同步線程
- 17. 線程同步
- 18. 線程同步
- 19. 使用tbb線程之間的同步
- 20. 多線程,線程同步
- 21. 使用異步調用與在線程中使用同步調用相同?
- 22. 單線程在多線程中不使用同步關鍵字
- 23. 線程同步VS進程同步
- 24. 使用同步的Java多線程不是線程安全的
- 25. 在java中同步線程
- 26. 在C中同步線程#
- 27. 在ruby中同步線程
- 28. 在線程中同步Hashmap
- 29. 使用.NET同步COM線程
- 30. 使用AutoResetEvent同步兩個線程
其他答案也很好?希望我可以選擇更多正確/有用的答案? – 2009-09-03 13:17:38