Java同一资源中的线程同步问题

Java Thread Synchronization problem in same resource

我正在尝试使用两个线程对同一个源进行操作。我为它设计了一个典型的生产者和消费者问题。在与生产者设置资源class中的值时,我想与消费者一一获取设置值。我想要的输出应该是这样的:

Producer -> Setting data = 0
Consumer -> Getting data = 0
Producer -> Setting data = 1
Consumer -> Getting data = 1
Producer -> Setting data = 2
Consumer -> Getting data = 2
Producer -> Setting data = 3
Consumer -> Getting data = 3
Producer -> Setting data = 4
Consumer -> Getting data = 4

这是我的资源 class:

public class Resource{
    
    private int value;
    private boolean current = false;
    public synchronized void setValue(int val) {
        while(current == true) {
        try {
            wait();
        }catch(Exception ex) {}}
        value = val;
        current = true;
        notifyAll();
    
    }
    
    public synchronized int getValue() {
        while(current == false) {
        try {
            wait();
        }catch(Exception ex) {}}
        
        current = false;
        notifyAll();
        return value;
    
    }
}

主要方法和生产者、消费者class在这里:

    class Producer extends Thread{

    private Resource rs;
    public Producer(Resource rs1) {
        rs = rs1;
    }
    public void run() {
        for(int i = 0 ; i < 5 ; i++) {
            rs.setValue(i);
            System.out.println("Producer -> Setting data = " + i);
            try {
                sleep(100);
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
        
    }
    
}

class Consumer extends Thread{
    
    private Resource rs;
    public Consumer(Resource rs1) {
        rs = rs1;
    }
    public void run() {
        int value = 0;
        for(int i = 0 ; i < 5; i++) {
            value = rs.getValue();
            System.out.println("Consumer -> Getting data= " + i);
            try {
                sleep(100);
            }catch(Exception ex) {
                ex.printStackTrace();
            }
        }
        
        
    }
    
}

public class Dependent {
    
    public static void main(String[] args) throws IOException {
        
        Resource res = new Resource();
        Producer p1 = new Producer(res);
        Consumer c1 = new Consumer(res);
    
        p1.start();
        c1.start();
        
    }

}

虽然我在资源class的方法中使用了synchronized、wait和notifyAll关键字,线程继续工作而不互相等待。我在哪里犯了错误?我在java一本书上看过类似这个代码示例的代码示例,好像没有问题。

当我在不添加当前布尔变量的情况下编写代码时,代码甚至无法运行。这就是为什么我必须通过从书中查找来添加它。线程不需要检查当前值就同步工作吗?

他们互相等待,但是线程同步操作多,比Thread.sleep(100 ) 所以你无法分辨。您的测试代码打印 'i' 而不是 'value',这是值得怀疑的。在这些线程之一(例如,在消费者中)摆脱 Thread.sleep(100) ,你会发现消费者仍然需要大约半秒才能完成 - 因为每次它都会等待大约 100 毫秒在资源上调用 .getValue(),因为该调用将阻塞(卡在 wait() 循环中)直到生产者调用 .setValue ,它每 100 毫秒只执行一次。

您的资源对象 'works',某些值 'works',但设计非常糟糕,从核心库重新创建现有的并更好地实现 类,例如java.util.concurrent.Latch,忽略中断,只会盲目地等待。

他们的 API 的命名也有点奇怪,因为 get 调用有相当大的副作用。 get 更像是一个 get and clear 操作:在一个 get 操作之后,另一个 get 操作将永远冻结线程,或者至少,直到某个线程设置一个值。

你怎么看?

import java.io.IOException;

class Resource {

    private volatile Integer value;
    public synchronized void setValue(int val) {
        while(value != null && !value.equals(val)) {
            try {
                wait();
            }catch(Exception ex) {}}
        value = val;
        notifyAll();

    }

    public synchronized int getValue() {
        while(value == null) {
            try {
                wait();
            }catch(Exception ex) {}}

        int answer = value;
        value = null;
        notifyAll();
        return answer;

    }
}

class Producer extends Thread{

    private Resource rs;
    public Producer(Resource rs1) {
        rs = rs1;
    }
    public void run() {
        for(int i = 0 ; i < 5 ; i++) {
            rs.setValue(i);
            System.out.println("Producer -> Setting data = " + i);
            try {
                sleep(100);
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }

    }

}

class Consumer extends Thread{

    private Resource rs;
    public Consumer(Resource rs1) {
        rs = rs1;
    }
    public void run() {
        for(int i = 0 ; i < 5; i++) {
            int value = rs.getValue();
            System.out.println("Consumer -> Getting data= " + value);
            try {
                sleep(100);
            }catch(Exception ex) {
                ex.printStackTrace();
            }
        }


    }

}

public class Dependent {

    public static void main(String[] args) throws IOException {

        Resource res = new Resource();
        Producer p1 = new Producer(res);
        Consumer c1 = new Consumer(res);

        p1.start();
        c1.start();

    }

}

class Resource {
    private static final int WAIT_VALUE = -1;
    private volatile int value = WAIT_VALUE;
    public synchronized void setValue(int val) {
        while(value > WAIT_VALUE && value != val) {
            try {
                wait();
            }catch(Exception ex) {}}
        value = val;
        notifyAll();

    }

    public synchronized int getValue() {
        while(value == WAIT_VALUE) {
            try {
                wait();
            }catch(Exception ex) {}}

        int answer = value;
        value = WAIT_VALUE;
        notifyAll();
        return answer;

    }
}