簡體   English   中英

Java自動識別線程死鎖並停止執行?

[英]Java automatically recognizes thread deadlock and stops execution?

我正在一個Java項目中模擬餐飲哲學家的問題

我從基本行為開始,每個線程都在think(),getForks(),eat()和putForks()中進行操作。 因此,無法防止死鎖或飢餓(故意執行)。

getForks()方法的工作方式如下:

getForks(){
    while(forks[rightFork]==0) /*0 means fork is not on the table, so wait*/
         print(Thread #id waiting for right fork);
    forks[rightFork] = 0;
    while(forks[leftFork]==0)
         print(Thread #id waiting for left fork);
    forks[leftFork = 0;
}

我在獲得右叉和左叉之間放置了一個sleep(5000),因此程序正在陷入死鎖(每個線程都握有右叉)。 但是,出乎意料的是,由於某種原因,一旦達到死鎖,執行就會停止。 我希望在死鎖期間將繼續打印“等待分叉的線程#id”消息,但事實並非如此。 一旦達到死鎖,就不再打印任何消息。

有什么線索嗎?

如果您想查看整個代碼,則為:

public class Philosophers{
    private static final int NUMBER = 3;
    private static final int MIN_SLEEP = 1000;
    private static final int MAX_SLEEP = 6000;
    private static Thread[] threads = new Thread[NUMBER];
    private static int[] forksArray = new int[8];

    private static void start(){
        System.out.println("Simulation started.");

        //Initialize forks array (1 means on the table)
        for(int i=0;i<7;i++)
            forksArray[i] = 1;

        //Create and start individual threads
        for(int i=0;i<NUMBER;i++){
            threads[i] = new Thread(new Philosopher(i));
            threads[i].start();
        }
    }

    public static void main(String[] args){
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                start();
            }
        });
    }

    private static class Philosopher implements Runnable{
        private int id;
        private int leftFork;
        private int rightFork;

        public void run(){
            System.out.println("Thread "+id+" started.");
            while(true){
                think();
                getForks();
                eat();
                putForks();
            }
        }

        public Philosopher(int id){
            this.id = id;
            this.rightFork = id;
            if(id==NUMBER - 1)
                this.leftFork = 0;
            else
                this.leftFork = id + 1;
        }

        public void think(){
            System.out.println("Thread "+id+" thinking...");
            try{
                int sleepInterval = MIN_SLEEP + (int)(Math.random() * ((MAX_SLEEP - MIN_SLEEP) + 1));
                Thread.sleep(sleepInterval);
            }
            catch(Exception e){
                System.out.println(e);
            }
        }

        public void getForks(){
            System.out.println("Thread "+id+" getting forks.");

            //Grab fork on the right
            while(forksArray[rightFork]==0)
                System.out.println("Thread "+id+" waiting for right fork");
            forksArray[rightFork] = 0;  

            try{
            Thread.sleep(5000);
        }   
        catch(Exception e){

        }

            //Grab fork on the left
            while(forksArray[leftFork]==0);
            System.out.println("Thread "+id+" waiting for left fork");
            forksArray[leftFork] = 0;           
        }

        public void eat(){
            System.out.println("Thread "+id+" eating.");
            try{
                Thread.sleep(2000);
            }
            catch(Exception e){
                System.out.println(e);
            }
        }

        public void putForks(){
            System.out.println("Thread "+id+" putting forks down.");
            forksArray[rightFork] = 1;
            forksArray[leftFork] = 1;
        }
    }
}

我認為您的問題在這里:

while(forksArray[leftFork]==0);
System.out.println("Thread "+id+" waiting for left fork");

的; while()表示它的主體為空語句。 因此,只有在循環終止后,下一行的println才會發生。

(順便說一句,這就是為什么人們經常建議始終使用{}進行循環,即使它們是單行的也是如此)

這並不是真正的死鎖:您不使用任何鎖! 這只是一個無限循環。

一個問題是您沒有使用正確的同步。 特別是,編譯器可以自由替換:

while (forksArray[leftFork] == 0);

有:

int temp = forksArray[leftFork];
while (temp == 0);

這可以在程序執行期間的任何時間發生。

只需使數組易失:

private static volatile int[] forksArray = new int[8];

應該使這個問題消失。 但是請注意,將數組標記為volatile僅會阻止執行優化-不足以使代碼線程安全。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM