Java 关于两个工人和一辆手推车的困惑。使用锁定和条件不';行不通

Java 关于两个工人和一辆手推车的困惑。使用锁定和条件不';行不通,java,multithreading,conditional-statements,locks,Java,Multithreading,Conditional Statements,Locks,当使用synchronized块或方法时,我们通过可变对象进行同步。但我不知道如何使用j.u.c.提供的带条件的锁。我正试图用两名工人和一辆带锁带条件的手推车来解决这个难题。当第一个工人向购物车添加重量时-第二次等待。当购物车已满时,第一个工人等待,第二个工人释放购物车。 我为每个工人创建两个线程,并使用一个购物车。但实际上只有一个线程执行(工人,增加重量)直到购物车装满。而不是程序块。我做错了什么,我误解了什么? 这就是我对这个谜题的实现 package puzzles.workers; p

当使用synchronized块或方法时,我们通过可变对象进行同步。但我不知道如何使用j.u.c.提供的带条件的锁。我正试图用两名工人和一辆带锁带条件的手推车来解决这个难题。当第一个工人向购物车添加重量时-第二次等待。当购物车已满时,第一个工人等待,第二个工人释放购物车。 我为每个工人创建两个线程,并使用一个购物车。但实际上只有一个线程执行(工人,增加重量)直到购物车装满。而不是程序块。我做错了什么,我误解了什么? 这就是我对这个谜题的实现

package puzzles.workers;

public enum WorkerType {
    ADDER, REDUCER;
}
购物车类

package puzzles.workers;
public class Cart {
private static final int INITIAL_CAPACITY = 10;
private static final int INITIAL_WEIGHT = 0;

private int capacity;
private int weight;



public Cart() {
    this(INITIAL_CAPACITY);
}

public Cart(int capacity) {
    this.capacity = capacity;
    weight = INITIAL_WEIGHT;
}

public void addWeight() {
    weight++;
}

public void reduceWeight() {
    weight--;
}

public int getCapacity() {
    return capacity;
}

public int getWeight() {
    return weight;
}
}
工人阶级

package puzzles.workers;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


public class WorkerWithLock implements Runnable {
    private final Cart cart;
    private WorkerType workerType;
    final Lock lock = new ReentrantLock();
    final Condition whenEmpty = lock.newCondition();
    final Condition whenFull = lock.newCondition();

    public WorkerWithLock(Cart cart, WorkerType workerType) {
        this.cart = cart;
        this.workerType = workerType;
    }

    @Override
    public void run() {
        while (true) {
            if (workerType == WorkerType.ADDER) {
                try {
                    addWeight();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
            } else {
                try {
                    reduceWeight();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    public void addWeight() throws InterruptedException {
        lock.lock();
        try {
            while (cart.getWeight() == (cart.getCapacity() - 1)) {
                whenFull.await();
            }
            cart.addWeight();
            System.out.println("++ weight is: " + cart.getWeight());
            whenEmpty.signalAll();
            Thread.sleep(500);
        } finally {
            lock.unlock();
        }
    }

    public void reduceWeight() throws InterruptedException {
        lock.lock();
        try {
            while (cart.getWeight() == 0) {
                whenEmpty.await();
            }
            cart.reduceWeight();
            System.out.println("-- weight is: " + cart.getWeight());
            whenFull.signalAll();
            Thread.sleep(500);
        } finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) throws InterruptedException {
    Cart cart = new Cart(5);
    WorkerWithLock adder = new WorkerWithLock(cart, WorkerType.ADDER);
    WorkerWithLock reducer = new WorkerWithLock(cart, WorkerType.REDUCER);

    new Thread(reducer).start();
    new Thread(adder).start();

}
}

这是一种竞争条件
这是因为两个线程都在等待。
一个在
addWeight
中,一个在
reduceWeight

如果重量为0,减速器首先停止。此时,加法器可能尚未启动。
如果权重=cpacity-1,则加法器停止

现在,两者都在等待中断()

编辑1。在代码中查看我的注释

public void addWeight() throws InterruptedException {
    lock.lock();
    try {
        while (cart.getWeight() == (cart.getCapacity() - 1)) {
            whenFull.await();  //<--   ADDER waits here 
        }
        cart.addWeight();
        System.out.println("++ weight is: " + cart.getWeight());
        whenEmpty.signalAll(); //<-- Never called since both are waiting
        Thread.sleep(500);
    } finally {
        lock.unlock();
    }
}

public void reduceWeight() throws InterruptedException {
    lock.lock();
    try {
        while (cart.getWeight() == 0) {
            whenEmpty.await(); //<-- REDUCER waits here
        }
        cart.reduceWeight();
        System.out.println("-- weight is: " + cart.getWeight());
        whenFull.signalAll(); //<-- Never called since both are waiting
        Thread.sleep(500);
    } finally {
        lock.unlock();
    }
}

有时多线程处理很难:)

Aha,但为什么signalAll()方法不中断等待?这是因为signalAll永远不会被调用,因为两者都在等待!几分钟后查看编辑。我看到了这个示例,并尝试对wait()和signal/signalAll()使用相同的方法。非常感谢您,尤其是对EDIT2。这有助于我理解!
final static Lock lock = new ReentrantLock();
final static Condition whenEmpty = lock.newCondition();
final static Condition whenFull = lock.newCondition();