简体   繁体   English

为什么我的线程突然停止在 Java 中?

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

I am supposed to be using two custom Semaphore classes (binary and counting) to print off letters in an exact sequence.我应该使用两个自定义信号量类(二进制和计数)以精确的顺序打印字母。 Here is the standard semaphore.这是标准信号量。

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();
}
}

And here is the binary semaphore:这是二进制信号量:

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();
}
}

Here is the main bulk of the code, except for a reason I can't work out why the threads stop after around thirty or so repetitions.这是代码的主要部分,除了我无法弄清楚为什么线程在大约 30 次左右重复后停止的原因。 Wait isn't called, the criteria for being true are being reached, so why aren't they working?没有调用等待,已经达到了真实的标准,那么为什么它们不起作用呢? Any help is much appreciated.任何帮助深表感谢。

        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();
                    }
                }
            }
        };

As @iggy points out the issue is related to fact that different threads are reading different values of value , because the way you access it isn't thread safe.正如@iggy 指出的那样,这个问题与不同的线程正在读取不同的value有关,因为您访问它的方式不是线程安全的。 Some threads may be using an old copy of the value.某些线程可能正在使用该值的旧副本。 Making it volatile will mean each thread access reads more consistent value:使其 volatile 意味着每个线程访问都读取更一致的值:

protected volatile int value;

Or switch to AtomicInteger which ensures thread consistent change to the int stored in value .或者切换到AtomicInteger以确保线程对存储在value中的 int 进行一致的更改。 You'll also need to replace the assignments using set/get/inc/decrement methods of AtomicInteger :您还需要使用AtomicInteger的 set/get/inc/decrement 方法替换分配:

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

Unfortunately, even with the above changes, you may find other issues because value could change in the duration between each Runnable's if statement, and the operations inside those if branches.不幸的是,即使进行了上述更改,您也可能会发现其他问题,因为每个 Runnable 的 if 语句与这些if分支内的操作之间的持续时间value可能会发生变化。

Also: replacing notify() by notifyAll() usually gives better multi-thread handling though I don't think this necessarily helps in your example.另外:用notifyAll()替换notify() ) 通常可以提供更好的多线程处理,尽管我认为这对您的示例不一定有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM