簡體   English   中英

為什么我的線程突然停止在 Java 中?

[英]Why are my threads suddenly stopping in Java?

我應該使用兩個自定義信號量類(二進制和計數)以精確的順序打印字母。 這是標准信號量。

public class Semaphore {

protected int value;

public Semaphore() {
    value = 0;
}

public Semaphore(int initial) {
    value = (initial >=0) ? initial : 0;
}

public synchronized void P() throws InterruptedException {
    while (value==0) {
        wait();
    }
    value--;
}

public synchronized void V() {
    value++;
    notify();
}
}

這是二進制信號量:

public class BinarySemaphore extends Semaphore {

public BinarySemaphore(boolean unlocked) {super(unlocked ? 1 : 0);}

public synchronized void P() throws InterruptedException{
    while(value==0) {
        wait();
    }
    value=0;
}

public synchronized void V() {
    value=1;
    notify();
}
}

這是代碼的主要部分,除了我無法弄清楚為什么線程在大約 30 次左右重復后停止的原因。 沒有調用等待,已經達到了真實的標准,那么為什么它們不起作用呢? 任何幫助深表感謝。

        BinarySemaphore binaryWXSemaphore = new BinarySemaphore(false);
        BinarySemaphore binaryYZSemaphore = new BinarySemaphore(false);

        Semaphore countingWSemaphore = new Semaphore();
        Semaphore countingYZSemaphore = new Semaphore();

        Runnable runnableW = () -> {
            while(true) {
                if (binaryWXSemaphore.value == 0 && countingYZSemaphore.value >= countingWSemaphore.value) {
                        binaryWXSemaphore.V();
                        countingWSemaphore.V();
                    System.out.println("W");
                }
            }
        };

        Runnable runnableX = () -> {
            while(true) {
                if (binaryWXSemaphore.value == 1) {
                    try {
                        binaryWXSemaphore.P();
                        System.out.println("X");

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Runnable runnableY = () -> {
            while(true) {
                if (binaryYZSemaphore.value == 0 && countingWSemaphore.value > countingYZSemaphore.value) {
                        binaryYZSemaphore.V();
                        countingYZSemaphore.V();
                    System.out.println("y");

                }

            }
        };

        Runnable runnableZ = () -> {
            while(true) {
                if (binaryYZSemaphore.value == 1 && countingWSemaphore.value > countingYZSemaphore.value) {
                    try {
                        binaryYZSemaphore.P();
                        countingYZSemaphore.V();
                        System.out.println("z");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        };

正如@iggy 指出的那樣,這個問題與不同的線程正在讀取不同的value有關,因為您訪問它的方式不是線程安全的。 某些線程可能正在使用該值的舊副本。 使其 volatile 意味着每個線程訪問都讀取更一致的值:

protected volatile int value;

或者切換到AtomicInteger以確保線程對存儲在value中的 int 進行一致的更改。 您還需要使用AtomicInteger的 set/get/inc/decrement 方法替換分配:

protected final  AtomicInteger value = new AtomicInteger();
// Then use value.set(0 / 1)
// or value.incrementAndGet / decrementAndGet

不幸的是,即使進行了上述更改,您也可能會發現其他問題,因為每個 Runnable 的 if 語句與這些if分支內的操作之間的持續時間value可能會發生變化。

另外:用notifyAll()替換notify() ) 通常可以提供更好的多線程處理,盡管我認為這對您的示例不一定有幫助。

暫無
暫無

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

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