简体   繁体   English

Java 多线程锁不能正常工作

[英]Java multithreading lock is not working correctly

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:我为此代码获得的 output 的示例部分是:

...... ……

...... ……

Withdraw Released Lock撤销已释放的锁

Withdraw Obtained Lock撤销获得的锁

Wait for deposit等待存款

Deposit Obtained Lock存款获得锁

Deposit 9 13存款 9 13

Deposit Released Lock存款释放锁

Withdraw 9 4退出 9 4

Withdraw Released Lock撤销已释放的锁

..... ......

..... ......

The question here is how Deposit thread obtained lock after window obtained lock.这里的问题是window获得锁后存款线程如何获得锁。 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 :)谁能解释一下output是怎么来的:提前谢谢:)

After Withdraw obtains the lock it checks if there is sufficient balance.Withdraw获得锁后,它会检查是否有足够的余额。 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.如果没有,则调用newdeposit.await ,这将释放锁,以便其他等待同一个锁的线程可以进入。这似乎是发生了什么: Withdraw进入该 if 块,开始等待, Deposit线程进来并存入一笔金额并唤醒Withdraw ,因此它可以继续更新的金额。 Once a notification is received, await locks and returns, so Withdraw continues execution with lock acquired.一旦收到通知, await锁定并返回,因此Withdraw继续执行并获得锁定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM