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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

打破冷漠僵局文章_研究僵局–第1部分

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

打破冷漠僵局文章

我敢肯定我們都去過那里:太晚了,您餓了,您的服務(wù)器已掛起,或者您的應(yīng)用程序正在以蝸牛的速度運(yùn)行,并且有人喘著粗氣想要您解決問題,然后再去解決。 您的應(yīng)用程序意外掛起的可能原因之一是稱為死鎖的線程問題。

無需贅述,線程可以處于多種狀態(tài)之一,如下面的UML狀態(tài)圖所示……

…死鎖與BLOCKED狀態(tài)有關(guān),API文檔將其定義為“一個(gè)等待監(jiān)視器鎖定而被阻塞的線程”。

那么,什么是僵局? 簡而言之,在給定兩個(gè)線程A和B的情況下,當(dāng)線程A由于等待線程B釋放監(jiān)視器鎖定而阻塞時(shí),線程B因等待線程A釋放相同的監(jiān)視器鎖定而阻塞而發(fā)生死鎖。

但是,事情可能比這更復(fù)雜,因?yàn)樗梨i可能包含一堆線程。 例如,線程A因?yàn)檎诘却€程B而阻塞,線程B因?yàn)檎诘却€程C而阻塞,線程C因?yàn)檎诘却€程D而阻塞,所以線程D因?yàn)檎诘却鼸,E而阻塞,因?yàn)樗诘却鼺和F阻塞,因?yàn)樗诘却鼳。

訣竅是找出哪些線程被阻塞以及為什么被阻塞,這是通過從應(yīng)用程序中獲取線程轉(zhuǎn)儲來完成的。 線程轉(zhuǎn)儲只是快照報(bào)告,顯示給定時(shí)間點(diǎn)所有應(yīng)用程序線程的狀態(tài)。 有幾種工具和技術(shù)可以幫助您掌握線程轉(zhuǎn)儲,包括jVisualVM , jstack和unix kill命令。 但是,在獲取和解釋線程轉(zhuǎn)儲之前,我需要一些代碼來創(chuàng)建死鎖

我為此選擇的方案是簡單的銀行帳戶轉(zhuǎn)帳之一。 這個(gè)想法是,有一個(gè)余額轉(zhuǎn)移程序正在運(yùn)行,該程序使用一堆線程在不同帳戶之間隨機(jī)轉(zhuǎn)移各種金額。 在此程序中,使用以下非常簡單的Account類表示銀行帳戶:

public class Account {private final int number;private int balance;public Account(int number, int openingBalance) {this.number = number;this.balance = openingBalance;}public void withdraw(int amount) throws OverdrawnException {if (amount > balance) {throw new OverdrawnException();}balance -= amount;}public void deposit(int amount) {balance += amount;}public int getNumber() {return number;}public int getBalance() {return balance;} }

上面的類為銀行帳戶建模,該銀行帳戶具有帳號和余額屬性,以及諸如deposit(...)和withdraw(...) 。 如果要提取的金額大于可用余額,則withdraw(...)將引發(fā)一個(gè)簡單的已檢查異常OverdrawnException 。

示例代碼中其余的類是DeadlockDemo及其嵌套類BadTransferOperation 。

public class DeadlockDemo {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[]) {DeadlockDemo demo = new DeadlockDemo();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);}}// This will never get to here...System.out.println("Thread Complete: " + threadNum);}private void printNewLine(int columnNumber) {if (columnNumber % MAX_COLUMNS == 0) {System.out.print("\n");}}/*** The clue to spotting deadlocks is in the nested locking - synchronized keywords. Note that the locks DON'T* have to be next to each other to be nested.*/private void transfer(Account fromAccount, Account toAccount, int transferAmount) throws OverdrawnException {synchronized (fromAccount) {synchronized (toAccount) {fromAccount.withdraw(transferAmount);toAccount.deposit(transferAmount);}}}} }

DeadlockDemo提供了創(chuàng)建DeadlockDemo的應(yīng)用程序框架。 它有兩個(gè)簡單的任務(wù): setup()和run() 。 setup()創(chuàng)建10個(gè)帳戶,并使用一個(gè)帳號和一個(gè)隨機(jī)的期初余額對其進(jìn)行初始化。 run()創(chuàng)建嵌套類BadTransferOperation 20個(gè)實(shí)例,該實(shí)例僅擴(kuò)展Thread并使它們開始運(yùn)行。 請注意,用于線程數(shù)和帳戶數(shù)的值完全是任意的。

BadTransferOperation是所有動(dòng)作發(fā)生的地方。 它的run()方法循環(huán)循環(huán)10000次,從accounts列表中隨機(jī)選擇兩個(gè)帳戶,并將0到1000之間的隨機(jī)數(shù)從一個(gè)accounts轉(zhuǎn)移到另一個(gè)accounts 。 如果fromAccount中的資金不足,則會(huì)引發(fā)異常,并在屏幕上顯示“-”。 如果一切順利,并且傳輸成功,則為“?!?。 在屏幕上打印。

事情的核心是包含FAULTY同步代碼的方法transfer(Account fromAccount, Account toAccount, int transferAmount) :

synchronized (fromAccount) {synchronized (toAccount) {fromAccount.withdraw(transferAmount);toAccount.deposit(transferAmount);}}

此代碼首先鎖定fromAccount ,然后toAccount轉(zhuǎn)移現(xiàn)金,隨后釋放這兩個(gè)鎖定前。

給定兩個(gè)線程A和B以及帳戶1和2,那么當(dāng)線程A鎖定其編號為1的fromAccount并嘗試將其鎖定為帳戶2的toAccount ,將出現(xiàn)問題。同時(shí),線程B鎖定其fromAccount ,編號2和嘗試鎖定其toAccount ,即帳戶號1。因此,線程A在線程B上被toAccount ,線程B在線程A上被阻塞–死鎖。

如果運(yùn)行此應(yīng)用程序,則將獲得一些類似于以下內(nèi)容的輸出:

…隨著程序突然停止。

現(xiàn)在,我有一個(gè)死鎖的應(yīng)用程序,我的下一個(gè)博客實(shí)際上將掌握線程轉(zhuǎn)儲,并了解它的全部含義。

參考: Captain Debug's Blog博客中的調(diào)查死鎖–第1部分,來自我們的JCG合作伙伴 Roger Hughes。


翻譯自: https://www.javacodegeeks.com/2012/10/investigating-deadlocks-part-1.html

打破冷漠僵局文章

總結(jié)

以上是生活随笔為你收集整理的打破冷漠僵局文章_研究僵局–第1部分的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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