Java 我们为什么要使用条件和什么';阻塞和等待的区别是什么
《核心Java》一书中有一个例子,它将资金从一个帐户转移到另一个帐户。我不知道条件的用处是什么?书中告诉我们: 如果我们只是无条件地锁定和等待,它会出现死锁: 当前线程现在已停用并放弃锁定。这让 在另一个线程中,我们希望可以增加帐户余额Java 我们为什么要使用条件和什么';阻塞和等待的区别是什么,java,multithreading,locking,conditional-statements,Java,Multithreading,Locking,Conditional Statements,《核心Java》一书中有一个例子,它将资金从一个帐户转移到另一个帐户。我不知道条件的用处是什么?书中告诉我们: 如果我们只是无条件地锁定和等待,它会出现死锁: 当前线程现在已停用并放弃锁定。这让 在另一个线程中,我们希望可以增加帐户余额 Lock锁定代码,条件放弃锁定,但我不知道什么是条件,为什么不在钱不够的时候简单地解锁区块? 线程状态阻塞和等待之间有什么区别? 阻塞:线程无法运行; 等待:线程不能运行太多。 有什么不同 另一个问题: while (accounts[from] < am
Lock
锁定代码,条件放弃锁定,但我不知道什么是条件,为什么不在钱不够的时候简单地解锁区块?
线程状态阻塞和等待之间有什么区别?
阻塞:线程无法运行;
等待:线程不能运行太多。
有什么不同
另一个问题:
while (accounts[from] < amount) {
...
sufficientFunds.await();
我认为在本例中,以
synchronized
为例,修改了Lock
的使用(对于最新的图书修订版,但当然不是没有错误)。对于已同步的代码
,没有问题:
private final double[] accounts;
private Condition sufficientFunds;
public synchronized void transfer(int from, int to, int amount)
{
try {
while (accounts[from] < amount) {
// wait . . . }
// transfer funds . . .
} finally {
this.notifyAll();
}
}
而不是
if (accounts[from] < amount) {
if(账户[来源]<金额){
因为我们希望得到方法调用的积极结果,但我们不能保证另一个线程将所有丢失的钱都提供给我们期望的帐户。
例如,如果你是一家银行,你会打电话给它
减少(约翰,1000)
但是客户约翰没有足够的钱(500美元而不是1000美元)如果你的reduce操作包装在if
而不是while
中,你将尝试只等待一次。你运气不好,此时银行里没有客户。因此你进入if
-阻塞等待一段时间并再次锁定,但你帐户上的金额没有变化(仍然是500美元)。您不执行重复检查(因为是if块而不是while),而是转到传输操作,这几乎不是我们真正想要的
方法
sufficientFunds.wait();
必须在其中执行三个操作:releaseLock(),wait(),lock()。这意味着我们释放锁以允许另一个线程与bank一起工作,并等待它完成操作,然后我们获取锁以再次执行余额检查并进行计划的transfer()
如果我们现在有足够的钱。首先,while阻塞的原因是:
它里面的代码只是在那一行等待线程。循环的编写只是为了在将来线程收到通知时(通过任何机制,例如添加了资金并在此之后使用notifyAll的线程),它将再次检查while循环中给出的条件。如果金额仍然大于帐户,它将再次进入等待条件并离开锁。
这将允许其他线程添加资金,然后再次让上述关注的线程尝试while条件。
一旦while条件失败,它将不会等待并继续转移资金。因此,它将通过unblock条件离开锁
阻塞和等待之间的区别:
<>如果我们集中精力使用正确的等待,我们可以避免一个被称为阻塞的状态。当我们等待时,我们认为代码是以线程将彼此正确地通知而不创建死锁的方式编写的。
如果thread1正在等待一个依赖于thread2的条件,而thread2正在等待一个依赖于thread1的条件,则会发生死锁或阻塞。对类
银行有一个特殊要求:如果要求它从一个帐户向另一个帐户转账,而源帐户上没有足够的钱,则必须等待,直到存入足够的资金以使转账成为可能。您可以运行循环,检查每次迭代是否有足够的资金,并仅在满足此条件时获取锁:
while (true) {
if (accounts[from] >= amount) {
bankLock.lock();
try {
if (account[from] >= amount) {
// do the transfer here...
break;
}
} finally {
bankLock.unlock();
}
}
}
但这种做法:
- 将CPU资源浪费在不断的检查上(这是什么意思
在几小时或几天内存款是否足够?)
- 看起来笨重而不地道
- 不总是有效的(原因不在这个问题的范围之内,如果你感兴趣,我可以在评论中给出解释的链接)
因此,你需要一种机制,告诉你你只是在等待账户中的一些变化。如果没有人在账户中存款,那么反复检查账户中的金额是浪费的。还有更多——你还需要在有人存款后立即获得锁,这样你就可以专门检查新账户的密码泰特,决定你是否可以转学
你还必须记住,存款不是账户上唯一允许的操作。例如,也有取款。如果有人取款,就没有必要检查你的账户是否有转帐的可能性,因为我们确信现在存款更少了。因此,我们想在存款上被唤醒,但不想成为一名银行经理我们需要以某种方式将他们分开。这就是条件发挥作用的地方
Condition是一个实现Condition
接口的对象。它只是一个抽象,允许您将锁定/等待逻辑分成几个部分。在我们的例子中,我们可以有两个条件:一个用于增加帐户余额,另一个用于减少(例如,如果有人正在等待将银行帐户归零以关闭它):
现在,您不需要在循环中进行数以百万计的检查,您可以以这样的方式组织您的程序:只有在有人为帐户提供资金时,您才可以唤醒并检查帐户:
private final double[] accounts;
private Lock bankLock;
private Condition sufficientFunds;
public void transfer(int from, int to, int amount) {
bankLock.lock();
try {
while (accounts[from] < amount) {
sufficientFunds.await();
}
// transfer funds ...
sufficientFunds.signalAll();
} finally {
bankLock.unlock();
}
}
public void deposit(int to, int amount) {
bankLock.lock();
try {
// deposit funds...
sufficientFunds.signalAll();
} finally {
bankLock.unlock();
}
}
私人最终双[]账户;
私家锁;
私人条件足够资金;
公共无效转账(整笔自、整笔至、整笔金额){
锁;
试试{
while(账户[来源]<金额){
足够的资金。等待();
}
//转移资金。。。
足够的资金。signalAll();
}
while (accounts[from] < amount) {
if (accounts[from] < amount) {
while (true) {
if (accounts[from] >= amount) {
bankLock.lock();
try {
if (account[from] >= amount) {
// do the transfer here...
break;
}
} finally {
bankLock.unlock();
}
}
}
sufficientFunds = bankLock.newCondition();
decreasedFunds = bankLock.newCondition();
private final double[] accounts;
private Lock bankLock;
private Condition sufficientFunds;
public void transfer(int from, int to, int amount) {
bankLock.lock();
try {
while (accounts[from] < amount) {
sufficientFunds.await();
}
// transfer funds ...
sufficientFunds.signalAll();
} finally {
bankLock.unlock();
}
}
public void deposit(int to, int amount) {
bankLock.lock();
try {
// deposit funds...
sufficientFunds.signalAll();
} finally {
bankLock.unlock();
}
}