日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

研究僵局–第4部分:修复代码

發(fā)布時(shí)間:2023/12/3 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 研究僵局–第4部分:修复代码 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在這個(gè)簡(jiǎn)短的博客系列的最后BadTransferOperation中,我一直在討論分析死鎖,我將修復(fù)BadTransferOperation代碼。 如果您看過(guò)本系列的其他博客 ,那么您將知道,為了達(dá)到這一點(diǎn),我創(chuàng)建了死鎖的演示代碼,展示了如何掌握線程轉(zhuǎn)儲(chǔ),然后分析了線程轉(zhuǎn)儲(chǔ),弄清楚發(fā)生僵局的位置和方式。 為了節(jié)省空間,下面的討論同時(shí)引用了本系列第1部分中的Account和DeadlockDemo類,其中包含完整的代碼清單。

教科書中有關(guān)死鎖的描述通常是這樣的:“線程A將獲得對(duì)象1的鎖定,并等待對(duì)象2的鎖定,而線程B將獲得對(duì)象2的鎖定,同時(shí)等待對(duì)象1的鎖定”。 我以前的博客中顯示的堆積,并在下面突出顯示,是一個(gè)真實(shí)的死鎖,其他線程,鎖和對(duì)象陷入了直接,簡(jiǎn)單,理論上的死鎖情況。

Found one Java-level deadlock: ============================= 'Thread-21':waiting to lock monitor 7f97118bd560 (object 7f3366f58, a threads.deadlock.Account),which is held by 'Thread-20' 'Thread-20':waiting to lock monitor 7f97118bc108 (object 7f3366e98, a threads.deadlock.Account),which is held by 'Thread-4' 'Thread-4':waiting to lock monitor 7f9711834360 (object 7f3366e80, a threads.deadlock.Account),which is held by 'Thread-7' 'Thread-7':waiting to lock monitor 7f97118b9708 (object 7f3366eb0, a threads.deadlock.Account),which is held by 'Thread-11' 'Thread-11':waiting to lock monitor 7f97118bd560 (object 7f3366f58, a threads.deadlock.Account),which is held by 'Thread-20'


如果將上面的文本和圖像與以下代碼相關(guān)聯(lián),則可以看到Thread-20已鎖定其fromAccount對(duì)象( fromAccount ),正在等待鎖定其toAccount對(duì)象(e98)

private void transfer(Account fromAccount, Account toAccount, int transferAmount) throws OverdrawnException {synchronized (fromAccount) {synchronized (toAccount) {fromAccount.withdraw(transferAmount);toAccount.deposit(transferAmount);}}}

不幸的是,由于時(shí)序問(wèn)題, Thread-20無(wú)法獲得對(duì)對(duì)象e98的鎖定,因?yàn)樗诘却齌hread-4釋放對(duì)該對(duì)象的鎖定。 Thread-4無(wú)法釋放鎖,因?yàn)樗诘却齌hread-7 , Thread-7正在等待Thread-11而Thread-11正在等待Thread-20釋放對(duì)對(duì)象f58的鎖。 這個(gè)現(xiàn)實(shí)世界的僵局只是教科書描述的一個(gè)更復(fù)雜的版本。

這段代碼的問(wèn)題是,從下面的代碼片段中,您可以看到我正在從Accounts數(shù)組中隨機(jī)選擇兩個(gè)Account對(duì)象作為fromAccount和toAccount并將它們鎖定。 由于fromAccount和toAccount可以引用accounts數(shù)組中的任何對(duì)象,這意味著它們以隨機(jī)順序被鎖定。

Account toAccount = accounts.get(rnd.nextInt(NUM_ACCOUNTS));Account fromAccount = accounts.get(rnd.nextInt(NUM_ACCOUNTS));

因此, 解決方法是對(duì)Account對(duì)象的鎖定方式施加順序,并且只要順序一致,任何順序都可以執(zhí)行。

private void transfer(Account fromAccount, Account toAccount, int transferAmount) throws OverdrawnException {if (fromAccount.getNumber() > toAccount.getNumber()) {synchronized (fromAccount) {synchronized (toAccount) {fromAccount.withdraw(transferAmount);toAccount.deposit(transferAmount);}}} else {synchronized (toAccount) {synchronized (fromAccount) {fromAccount.withdraw(transferAmount);toAccount.deposit(transferAmount);}}}}

上面的代碼顯示了此修復(fù)程序。 在此代碼中,我使用帳號(hào)來(lái)確保首先鎖定具有最高帳號(hào)的Account對(duì)象,以便永遠(yuǎn)不會(huì)出現(xiàn)以上的死鎖情況。

以下代碼是此修復(fù)程序的完整列表:

public class AvoidsDeadlockDemo {private static final int NUM_ACCOUNTS = 10;private static final int NUM_THREADS = 20;private static final int NUM_ITERATIONS = 100000;private static final int MAX_COLUMNS = 60;static final Random rnd = new Random();List<Account> accounts = new ArrayList<Account>();public static void main(String args[]) {AvoidsDeadlockDemo demo = new AvoidsDeadlockDemo();demo.setUp();demo.run();}void setUp() {for (int i = 0; i < NUM_ACCOUNTS; i++) {Account account = new Account(i, rnd.nextInt(1000));accounts.add(account);}}void run() {for (int i = 0; i < NUM_THREADS; i++) {new BadTransferOperation(i).start();}}class BadTransferOperation extends Thread {int threadNum;BadTransferOperation(int threadNum) {this.threadNum = threadNum;}@Overridepublic void run() {for (int i = 0; i < NUM_ITERATIONS; i++) {Account toAccount = accounts.get(rnd.nextInt(NUM_ACCOUNTS));Account fromAccount = accounts.get(rnd.nextInt(NUM_ACCOUNTS));int amount = rnd.nextInt(1000);if (!toAccount.equals(fromAccount)) {try {transfer(fromAccount, toAccount, amount);System.out.print(".");} catch (OverdrawnException e) {System.out.print("-");}printNewLine(i);}}System.out.println("Thread Complete: " + threadNum);}private void printNewLine(int columnNumber) {if (columnNumber % MAX_COLUMNS == 0) {System.out.print("\n");}}/*** This is the crucial point here. The idea is that to avoid deadlock you need to ensure that threads can't try* to lock the same two accounts in the same order*/private void transfer(Account fromAccount, Account toAccount, int transferAmount) throws OverdrawnException {if (fromAccount.getNumber() > toAccount.getNumber()) {synchronized (fromAccount) {synchronized (toAccount) {fromAccount.withdraw(transferAmount);toAccount.deposit(transferAmount);}}} else {synchronized (toAccount) {synchronized (fromAccount) {fromAccount.withdraw(transferAmount);toAccount.deposit(transferAmount);}}}}} }

在我的示例代碼,死鎖的發(fā)生是因?yàn)闀r(shí)機(jī)問(wèn)題,嵌套的synchronized在我的關(guān)鍵字BadTransferOperation類。 在此代碼中, synchronized關(guān)鍵字位于相鄰的行上; 但是,最后一點(diǎn)是,值得注意的是, synchronized關(guān)鍵字在代碼中的什么位置都沒(méi)關(guān)系(它們不必相鄰)。 只要您使用同一線程鎖定兩個(gè)(或更多)不同的監(jiān)視對(duì)象,就會(huì)發(fā)生排序和死鎖。

有關(guān)更多信息,請(qǐng)參閱本系列中的其他博客 。

該系列以及其他博客的所有源代碼都可以在Github上找到,網(wǎng)址為git://github.com/roghughe/captaindebug.git

參考: 調(diào)查死鎖-第4部分:來(lái)自Captain Debug博客博客的JCG合作伙伴 Roger Hughes 修復(fù)代碼 。

翻譯自: https://www.javacodegeeks.com/2012/11/investigating-deadlocks-part-4-fixing-the-code.html

總結(jié)

以上是生活随笔為你收集整理的研究僵局–第4部分:修复代码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。