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