英文:
Java multithreading lock is not working correctly
问题
完整的程序如下:
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
public class AccountWithConditionsUser {
private static Account account = new Account();
public static void main(String[] args) {
System.out.println("Thread 1\t\tThread 2\t\tBalance");
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(new DepositTask());
executor.execute(new WithdrawTask());
executor.shutdown();
while (!executor.isShutdown()) {
}
}
public static class DepositTask implements Runnable{
public void run() {
try {
while (true) {
account.deposit((int)(Math.random() * 10) + 1);
Thread.sleep(1000);
}
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
public static class WithdrawTask implements Runnable{
public void run() {
while (true) {
account.withdraw((int)(Math.random() * 10) + 1);
}
}
}
private static class Account {
private static Lock lock = new ReentrantLock(true);
private static Condition newDeposit = lock.newCondition();
private int balance = 0;
public int getBalance() {
return balance;
}
public void withdraw(int amount) {
lock.lock();
System.out.println("->Withdraw Obtained Lock");
try {
while (balance < amount) {
System.out.println("\t\t\tWait for deposit");
newDeposit.await();
}
balance -= amount;
System.out.println("\t\t\tWithdraw " + amount + "\t\t" + getBalance());
}
catch (Exception e) {
e.printStackTrace();
}
finally {
System.out.println("->Withdraw Released Lock");
lock.unlock();
}
}
public void deposit(int amount) {
lock.lock();
System.out.println("->Deposit Obtained Lock");
try {
balance += amount;
System.out.println("Deposit " + amount + "\t\t\t\t\t" + getBalance());
newDeposit.signalAll();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
System.out.println("->Deposit Released Lock");
lock.unlock();
}
}
}
}
部分输出示例如下:
......
......
Withdraw Released Lock
Withdraw Obtained Lock
Wait for deposit
Deposit Obtained Lock
Deposit 9 13
Deposit Released Lock
Withdraw 9 4
Withdraw Released Lock
.....
.....
这里的问题是为什么存款线程在窗口线程之后获得了锁。按理说,一旦锁被获得,其他线程就不能再获得它,对吗?或者是因为 signal 方法的原因?有人能解释一下这个输出是怎么来的吗?提前谢谢
英文:
The whole program is :
import java.util.concurrent.*;
import java.util.concurrent.locks.*;
public class AccountWithConditionsUser {
private static Account account = new Account();
public static void main(String[] args) {
System.out.println("Thread 1\t\tThread 2\t\tBalance");
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(new DepositTask());
executor.execute(new WithdrawTask());
executor.shutdown();
while(!executor.isShutdown()) {
}
}
public static class DepositTask implements Runnable{
public void run() {
try {
while(true) {
account.deposit((int)(Math.random()* 10)+ 1);
Thread.sleep(1000);
}
}
catch(InterruptedException ex) {
ex.printStackTrace();
}
}
}
public static class WithdrawTask implements Runnable{
public void run() {
while(true) {
account.withdraw((int)(Math.random() * 10) + 1);
}
}
}
private static class Account{
private static Lock lock = new ReentrantLock(true);
private static Condition newDeposit = lock.newCondition();
private int balance = 0;
public int getBalance() {
return balance;
}
public void withdraw(int amount) {
lock.lock();
System.out.println("->Withdraw Obtained Lock");
try {
while(balance < amount) {
System.out.println("\t\t\tWait for deposit");
newDeposit.await();
}
balance-=amount;
System.out.println("\t\t\tWithdraw "+ amount + "\t\t" + getBalance());
}
catch(Exception e) {
e.printStackTrace();
}
finally {
System.out.println("->Withdraw Released Lock");
lock.unlock();
}
}
public void deposit(int amount) {
lock.lock();
System.out.println("->Deposit Obtained Lock");
try {
balance+=amount;
System.out.println("Deposit "+ amount + "\t\t\t\t\t" + getBalance());
newDeposit.signalAll();
}
catch(Exception e) {
e.printStackTrace();
}
finally {
System.out.println("->Deposit Released Lock");
lock.unlock();
}
}
}
}
And the sample part of the output I got for this code is:
......
......
Withdraw Released Lock
Withdraw Obtained Lock
Wait for deposit
Deposit Obtained Lock
Deposit 9 13
Deposit Released Lock
Withdraw 9 4
Withdraw Released Lock
.....
.....
The question here is how Deposit thread obtained lock after window obtained lock. Isn't it supposed to be that once a lock is obtained it can't be obtained by any other thread! Or is it because of the signal methods? Can anyone please explain how that output came?
Thanks in advance
答案1
得分: 0
在获取锁之后,Withdraw
函数会检查是否有足够的余额。如果没有足够的余额,则会调用 newdeposit.await
,这将释放锁,以便等待相同锁的其他线程可以进入。这似乎就是发生的情况:Withdraw
进入了该 if 代码块,开始等待,然后 Deposit
线程进来存入一定金额并唤醒了 Withdraw
,以便它可以继续使用更新后的金额。一旦收到通知,await
会释放锁并返回,因此 Withdraw
在获得锁的情况下继续执行。
英文:
After Withdraw
obtains the lock it checks if there is sufficient balance. If there is not, then it calls newdeposit.await
, which will release the lock so other threads waiting on the same lock can get in. That appears to be what happened: Withdraw
entered into that if-block, started waiting, the Deposit
thread came in and deposited an amount and woke Withdraw
up, so it can continue with the updated amount. Once a notification is received, await
locks and returns, so Withdraw
continues execution with lock acquired.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论