微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决同一资源中的Java线程同步问题

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

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

这是我的资源类:

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

还有main方法和Producer,Consumer类:

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

}

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

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

解决方法

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

您的资源对象“有效”,对于“有效”的某些价值,但设计很差,从核心库(例如 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;

    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。