日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

JAVA線程死鎖

Java線程死鎖發生的常見行為是雙方互相持有對方需要的鎖:即兩個或多個線程在等待彼此持有的鎖,導致所有線程都無法繼續執行下去。這種情況通常會產生一個循環等待的場景。

舉例代碼:

public class DeadlockExample {
    private static Object lockA = new Object();
    private static Object lockB = new Object();

    public static void main(String[] args) {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lockA) {
                    System.out.println("Thread 1 acquired lock A");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (lockB) {
                        System.out.println("Thread 1 acquired lock B");
                    }
                }
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lockB) {
                    System.out.println("Thread 2 acquired lock B");
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (lockA) {
                        System.out.println("Thread 2 acquired lock A");
                    }
                }
            }
        });

        thread1.start();
        thread2.start();
    }
}

為避免死鎖,可以采取以下措施:

 

  1. 避免嵌套鎖
  2. 使用同步塊代替同步方法
  3. 按照固定順序獲取鎖
  4. 可以使用Lock對象代替synchronized關鍵字
  5. 使用Semaphore避免死鎖
  6. 使用ThreadLocal為每個線程提供獨立的變量副本,避免多個線程之間共享變量導致的死鎖問題
  7. 避免長時間持有鎖,盡可能減少持有鎖的時間
  8. 使用非阻塞算法或無鎖算法

修改上述代碼

使用ReentrantLock

使用ReentrantLock時,需要將所有涉及到共享資源的代碼放在lock()和unlock()方法之間,才能保證線程安全。在之前的代碼示例中,if代碼塊沒有被包括在lock()和unlock()方法之間,因此不具備線程安全性。

 

以下是修改后的示例代碼:

public class DeadlockExample {
    private static final ReentrantLock lockA = new ReentrantLock();
    private static final ReentrantLock lockB = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    lockA.lock();
                    System.out.println("Thread 1 acquired lock A");
                    Thread.sleep(100);
                    if (lockB.tryLock(100, TimeUnit.MILLISECONDS)) {
                        System.out.println("Thread 1 acquired lock B");
                        Thread.sleep(100);
                    } else {
                        System.out.println("Thread 1 failed to acquire lock B, aborting");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    if (lockB.isHeldByCurrentThread()) {
                        lockB.unlock();
                        System.out.println("Thread 1 released lock B");
                    }
                    lockA.unlock();
                    System.out.println("Thread 1 released lock A");
                }
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    lockB.lock();
                    System.out.println("Thread 2 acquired lock B");
                    Thread.sleep(100);
                    if (lockA.tryLock(100, TimeUnit.MILLISECONDS)) {
                        System.out.println("Thread 2 acquired lock A");
                        Thread.sleep(100);
                    } else {
                        System.out.println("Thread 2 failed to acquire lock A, aborting");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    if (lockA.isHeldByCurrentThread()) {
                        lockA.unlock();
                        System.out.println("Thread 2 released lock A");
                    }
                    lockB.unlock();
                    System.out.println("Thread 2 released lock B");
                }
            }
        });

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();
    }
}

以上代碼中,在每個線程的run方法中,我們依次獲取兩把鎖,并在獲取到鎖之后進行相應的操作。在釋放鎖時,需要先判斷當前線程是否持有該鎖,如果是,則釋放該鎖,并打印相應的信息。

這樣修改后,就能保證線程安全和避免死鎖的問題了。

使用Semaphore

以下是修改后的示例代碼:

 

public class DeadlockExample {
    private static final Semaphore semaphoreA = new Semaphore(1);
    private static final Semaphore semaphoreB = new Semaphore(1);

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    semaphoreA.acquire();
                    System.out.println("Thread 1 acquired semaphore A");
                    Thread.sleep(100);

                    while (!semaphoreB.tryAcquire()) {
                        semaphoreA.release();
                        System.out.println("Thread 1 released semaphore A and waiting for semaphore B");
                        semaphoreA.acquire();
                        System.out.println("Thread 1 acquired semaphore A again");
                    }

                    System.out.println("Thread 1 acquired semaphore B");
                    Thread.sleep(100);

                    semaphoreB.release();
                    System.out.println("Thread 1 released semaphore B");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphoreA.release();
                    System.out.println("Thread 1 released semaphore A");
                }
            }
        });

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    semaphoreB.acquire();
                    System.out.println("Thread 2 acquired semaphore B");
                    Thread.sleep(100);

                    while (!semaphoreA.tryAcquire()) {
                        semaphoreB.release();
                        System.out.println("Thread 2 released semaphore B and waiting for semaphore A");
                        semaphoreB.acquire();
                        System.out.println("Thread 2 acquired semaphore B again");
                    }

                    System.out.println("Thread 2 acquired semaphore A");
                    Thread.sleep(100);

                    semaphoreA.release();
                    System.out.println("Thread 2 released semaphore A");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphoreB.release();
                    System.out.println("Thread 2 released semaphore B");
                }
            }
        });

        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();
    }
}

以上代碼中,如果全部使用acquire(),那么在當前線程獲取到第一個資源后,如果無法獲取第二個資源,就會釋放第一個資源,并進入等待狀態。然而,由于此時其他線程可能已經獲取了第一個資源并在等待第二個資源,因此當前線程可能永遠無法獲取到第二個資源,從而導致死鎖的發生。

 

為了避免這種情況,可以使用tryAcquire()方法來嘗試獲取第二個資源,如果無法獲取,則先釋放第一個資源再進行等待。

這樣修改后,就能保證線程安全和避免死鎖的問題了。

Java線程饑餓

Java中線程饑餓(Thread Starvation)是指某個或某些線程無法獲得所需的資源,從而無法繼續執行下去,導致程序出現假死等異常情況。

 

舉個例子,如果一個高優先級的線程一直占用某個共享資源,并且低優先級的線程總是無法獲取該資源,那么這些低優先級的線程就會一直處于等待狀態,無法執行下去,從而導致線程饑餓的發生。

另外,線程饑餓也可能發生在多個線程競爭同一資源時,如果某些線程總是能夠比其他線程更快地獲取到該資源,那么其他線程就會一直處于等待狀態,無法及時完成任務,從而導致線程饑餓的發生。

為避免線程饑餓的發生,可以采取以下措施:

  1. 合理設計線程優先級,盡量保證每個線程都能有機會獲取到所需的資源。
  2. 使用公平鎖來保證資源的公平分配,避免某個線程長期占用某個資源。
  3. 盡量減少線程等待的時間,例如使用超時機制、避免死鎖等方式來盡早釋放資源,讓其他線程有機會獲取到資源。
  4. 對于一些不必要占用大量資源的線程,可以將其設置為低優先級或者使用線程池等方式來限制其數量,從而避免線程饑餓的發生。

總之,在編寫多線程程序時需要注意線程饑餓問題,并采取相應措施來保證程序的正常執行。

以下是一個簡單的代碼示例,模擬了線程饑餓的情況。

 

public class ThreadStarvationExample {
    private static final Object lock = new Object();

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            final int index = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (lock) {
                        System.out.println("Thread " + index + " acquired lock");
                        try {
                            // 模擬某些線程需要占用鎖較長時間
                            if (index == 2 || index == 3) {
                                Thread.sleep(5000);
                            } else {
                                Thread.sleep(1000);
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("Thread " + index + " released lock");
                    }
                }
            }).start();
        }
    }
}

以上代碼中,我們創建了10個線程,并對它們共享的一個鎖進行競爭。其中,第2個線程和第3個線程分別需要占用鎖5秒鐘和其他線程相比更久的時間。

如果運行以上代碼,我們可能會發現第2個線程和第3個線程總是優先獲得鎖,而其他線程則會等待較長時間才能獲取到鎖,從而導致這些線程在整個程序執行期間都無法正常執行下去,出現線程饑餓的情況。

為避免線程饑餓的發生,我們可以對占用鎖時間較長的線程做出調整,例如將它們設置為低優先級或者減少其持有鎖的時間等措施。

另外,我們還可以使用公平鎖來保證資源的公平分配,避免某個線程長期占用某個資源。以下是修改后的代碼示例:

 

public class ThreadStarvationExample {
    private static final ReentrantLock lock = new ReentrantLock(true);

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            final int index = i;
            new Thread(new Runnable() {
                @Override
                public void run() {
                    synchronized (lock) {
                        System.out.println("Thread " + index + " acquired lock");
                        try {
                            if (index == 2 || index == 3) {
                                // 將占用鎖時間較長的線程設置為低優先級
                                Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
                                Thread.sleep(5000);
                            } else {
                                Thread.sleep(1000);
                            }
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } finally {
                            // 減少持有鎖的時間,增加其他線程獲取鎖的機會
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            System.out.println("Thread " + index + " released lock");
                        }
                    }
                }
            }).start();
        }
    }
}

分享到:
標簽:線程
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定