我遇到两个似乎没有正确同步的线程的问题。我基本上有一个布尔值名称“被占用”。没有线程启动时设置为false。但是当一个人开始时,线程集被占用是真的我有一个有线程(运行)的类,他们调用下面的函数。
这是一个模拟银行示例,它接受金额(初始余额),然后随机执行提款和存款。我的教授提到了一些关于信号形成退出线程到存款线程的信息?这是如何运作的?撤销线程,它应该运行,直到余额为两个低并等待存款线程。我该怎么做?
package bank;
import java.util.Random;
import bank.Bank;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;
/**
*
* @author KJ4CC
*/
public class Action {
private Lock accessLock = new ReentrantLock();
private Condition cond = accessLock.newCondition();
//private Condition withdraw = accessLock.newCondition();
Random rand = new Random();
Object lock = new Object();
Bank getBalance = new Bank();
public void widthdrawl(int threadNum) throws InterruptedException {
int amount = rand.nextInt(50);
accessLock.lock();
if (getBalance.getbalance() > amount) {
getBalance.setBalance(getBalance.getbalance() - amount);
System.out.println("\t\t\tThread " + threadNum + " withdrawls " + amount + "\t Balance is " + getBalance.getbalance());
} else {
System.out.println("\t\t\tThread " + threadNum + " Failed to withdrawl " + amount + "\t Balance is " + getBalance.getbalance());
cond.await();
}
accessLock.unlock();
Thread.sleep(rand.nextInt(5));
}
public void deposit(int threadNum) throws InterruptedException {
int amount = rand.nextInt(200);
accessLock.lock();
getBalance.setBalance(getBalance.getbalance() + amount);
System.out.println("Thread " + threadNum + " Deposits " + amount + "\t\t\t\t Balance is " + getBalance.getbalance());
Thread.sleep(rand.nextInt(100));
cond.signal();
accessLock.unlock();
}
}
答案 0 :(得分:4)
您的Lock
和Condition
用法错误。您在没有在任何地方拨打lock()
的情况下呼叫unlock()
,并且在没有任何人呼叫signal()
的情况下您正在呼叫await()
。
请参阅documentation,了解您的问题的非常相关。
答案 1 :(得分:0)
首先,您必须标记occupid
变量volatile。如果没有此关键字,则更改一个线程中的变量值将无法在另一个线程中显示。
其次,您尝试为bank
实体实施外部同步策略。这样的想法基本上并不好:如果有人在没有正确同步的情况下使用相同的bank
,它就会打破内部银行状态。最好实施内部同步策略并允许银行自行保护其状态。
E.g。 Bank
类的API可能就像这样
class Bank {
double synchronize getBalance() { ... }
void synchronize deposit(double amount) { ... }
void synchronize widthdrawl(double amount) throw BankException { ... }
}
使用此设计,内部Bank
状态始终保持一致,任何 Bank
用户将等待自动完成当前银行操作。