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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

打破冷漠僵局文章

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

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

…死鎖與BLOCKED狀態有關,API文檔將其定義為“一個等待監視器鎖定而被阻塞的線程”。

那么,什么是僵局? 簡而言之,在給定兩個線程A和B的情況下,當線程A由于等待線程B釋放監視器鎖定而阻塞時,線程B因等待線程A釋放相同的監視器鎖定而阻塞而發生死鎖。

但是,事情可能比這更復雜,因為死鎖可能包含一堆線程。 例如,線程A因為正在等待線程B而阻塞,線程B因為正在等待線程C而阻塞,線程C因為正在等待線程D而阻塞,所以線程D因為正在等待E,E而阻塞,因為它正在等待F和F阻塞,因為它正在等待A。

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

我為此選擇的方案是簡單的銀行帳戶轉帳之一。 這個想法是,有一個余額轉移程序正在運行,該程序使用一堆線程在不同帳戶之間隨機轉移各種金額。 在此程序中,使用以下非常簡單的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(...)將引發一個簡單的已檢查異常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提供了創建DeadlockDemo的應用程序框架。 它有兩個簡單的任務: setup()和run() 。 setup()創建10個帳戶,并使用一個帳號和一個隨機的期初余額對其進行初始化。 run()創建嵌套類BadTransferOperation 20個實例,該實例僅擴展Thread并使它們開始運行。 請注意,用于線程數和帳戶數的值完全是任意的。

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

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

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

此代碼首先鎖定fromAccount ,然后toAccount轉移現金,隨后釋放這兩個鎖定前。

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

如果運行此應用程序,則將獲得一些類似于以下內容的輸出:

…隨著程序突然停止。

現在,我有一個死鎖的應用程序,我的下一個博客實際上將掌握線程轉儲,并了解它的全部含義。

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


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

打破冷漠僵局文章

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。