首頁 > Java > java教程 > 主體

Java 中的死鎖

WBOY
發布: 2024-08-30 15:40:06
原創
838 人瀏覽過

在Java中,死鎖是多執行緒的一種情況,執行緒1等待執行緒2取得物件鎖,執行緒2等待執行緒1取得物件鎖。這裡,線程1和線程2都互相等待釋放鎖。 Java 中的多執行緒程式可能會導致死鎖,因為關鍵字synchronized 會在等待與所提到的物件連結的監視器或鎖定時阻塞執行緒。讓我們在以下部分中看到死鎖的工作原理和範例。

開始您的免費軟體開發課程

網頁開發、程式語言、軟體測試及其他

死鎖是如何運作的?

如所討論的,同步方法可以鎖定程式碼的特定部分。對於Java中的每個對象,都會有一個鎖,同步是一種鎖定函數或程式碼區塊的技術,以確保一次只有1個執行緒可以存取該函數或程式碼區塊。

當特定執行緒需要執行同步函數時,它首先嘗試取得鎖定。同時,如果另一個執行緒已經收到鎖,則第一個執行緒將等待,直到執行緒 2 釋放鎖。儘管同步可以防止資料不一致的問題,但仍存在同步問題。

假設有 2 個線程,「線程 ​​1」和「線程 2」。執行緒 1 已取得物件 1 的鎖定,執行緒 2 已獲得物件 2 的鎖定。執行緒 1 執行方法 1,想要取得物件 2 的鎖定。但是,線程 2 已經獲得物件 2 的鎖定。

此外,執行緒2還需要取得物件1的鎖;但是,執行緒 1 擁有物件 1 上的鎖。此時,執行緒 1 和執行緒 2 這兩個執行緒都無法完成其執行,只能永遠等待該鎖定。這種情況稱為死鎖。

Java 中的死鎖範例

下面給出了提到的範例:

範例#1

實作死鎖的Java程式。

代碼:

public class DeadLockExample {
//main method
public static void main(String[] args) throws InterruptedException {
//create three objects 1, 2 and 3
Object o1 = new Object();
Object o2 = new Object();
Object o3 = new Object();
//create three threads 1, 2 and 3
Thread th1 = new Thread(new SynchronizationThread(o1, o2), "thread 1");
Thread th2 = new Thread(new SynchronizationThread(o2, o3), "thread 2");
Thread th3 = new Thread(new SynchronizationThread(o3, o1), "thread 3");
//start thread 1
th1.start();
//thread sleeps for 5000 seconds
Thread.sleep(5000);
//start thread 2
th2.start();
//thread sleeps for 5000 seconds
Thread.sleep(5000);
//start thread 3
th3.start();
}
}
class SynchronizationThread implements Runnable
{
private Object o1;
private Object o2;
public SynchronizationThread(Object o1, Object o2){
this.o1=o1;
this.o2=o2;
}
//function run
@Override
public void run() {
//store the name of the thread
String nm = Thread.currentThread().getName();
System.out.println( nm + " attaining lock on "+ o1 ) ;
synchronized (o1)
{
System.out.println( nm + " attained lock on "+ o1 ) ;
work();
System.out.println( nm + " attaining lock on "+ o2 ) ;
synchronized (o2) {
System.out.println( nm + " attained lock on "+ o2 );
work();
}
System.out.println( nm + " released lock on "+ o2 ) ;
}
System.out.println( nm + " released lock on "+ o1 ) ;
System.out.println( nm + " completed execution.") ;
}
//function work
private void work() {
try {
//thread sleeps
Thread.sleep(30000);
}
//catch the exception
catch (InterruptedException exc)
{
exc.printStackTrace();
}
}
}
登入後複製

輸出:

Java 中的死鎖

範例#2

在這個程式中,3個正在運行的執行緒共享一個資源,並且它們以獲取物件1上的鎖的方式運行,但是當它嘗試獲取物件2上的鎖時,它會進入等待狀態。為了防止死鎖,可以將程式碼重寫如下。

代碼:

public class DeadLockExample {
public static void main(String[] args) throws InterruptedException {
Object o1 = new Object();
Object o2 = new Object();
Object o3 = new Object();
Thread th1 = new Thread(new SynchronizationThread(o1, o2), "thread 1");
Thread th2 = new Thread(new SynchronizationThread(o2, o3), "thread 2");
Thread th3 = new Thread(new SynchronizationThread(o3, o1), "thread 3");
//start thread 1, 2 and 3
th1.start();
//thread sleeps for 5000 seconds
Thread.sleep(5000);
th2.start();
//thread sleeps for 5000 seconds
Thread.sleep(5000);
th3.start();
}
}
class SynchronizationThread implements Runnable{
private Object o1;
private Object o2;
public SynchronizationThread(Object o1, Object o2){
this.o1=o1;
this.o2=o2;
}
//function run
@Override
public void run() {
//store the name of the thread
String nm = Thread.currentThread().getName();
System.out.println( nm + " attaining lock on "+ o1 ) ;
synchronized (o1)
{
System.out.println( nm + " attained lock on "+ o1 ) ;
work();
}
System.out.println( nm + " released lock on "+ o1 ) ;
System.out.println( nm + " acquiring lock on " + o2 );
synchronized (o2) {
System.out.println( nm + " attained lock on "+ o2 );
work();
}
System.out.println( nm + " released lock on "+ o2 ) ;
System.out.println( nm + " released lock on "+ o1 ) ;
System.out.println( nm + " completed execution.") ;
}
//function work
private void work() {
try {
//thread sleeps
Thread.sleep(30000);
}
//catch the exception
catch (InterruptedException exc)
{
exc.printStackTrace();
}
}
}
登入後複製

輸出:

Java 中的死鎖

如何避免 Java 中的死鎖?

以下是有助於避免死鎖情況的指南。

1.避免嵌套鎖

巢狀鎖是導致死鎖的常見原因之一。如果另一資源已持有一個資源,請勿鎖定該資源以避免死鎖。如果使用者只使用 1 個對象,則不可能導致死鎖。

2.只鎖定需要的內容

人們建議僅鎖定必要的資源。但是,即使不需要,某些使用者也可能會嘗試鎖定資源。

3.避免無限期等待

如果兩個執行緒借助執行緒連線無限期地等待對方完成,就會發生死鎖。如果執行緒需要等待其他執行緒完成,最好使用具有等待執行緒完成的最大時間的 join。

以上是Java 中的死鎖的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!