【问题标题】:Java multithreading lock is not working correctlyJava 多线程锁无法正常工作
【发布时间】:2020-08-17 14:18:00
【问题描述】:

整个程序是:

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();
            }
        }
    }
}

我得到的这段代码输出的示例部分是:

......

......

撤销已释放的锁

撤销获得的锁

等待存款

存款获得锁

存款 9 13

存款释放锁

退出 9 4

撤销已释放的锁

.....

.....

这里的问题是窗口获得锁后存款线程如何获得锁。不是说一旦获得了锁,其他线程就无法获得!还是因为信号方法?谁能解释一下这个输出是怎么来的? 在此先感谢:)

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    Withdraw 获得锁后,它会检查是否有足够的余额。如果没有,那么它调用newdeposit.await,这将释放锁,以便其他等待同一个锁的线程可以进入。这似乎是发生了什么:Withdraw 进入那个 if 块,开始等待, Deposit 线程进来并存了一笔金额并唤醒了Withdraw,因此它可以继续更新金额。一旦收到通知,await 将锁定并返回,因此Withdraw 会继续执行并获得锁定。

    【讨论】:

    • 感谢您的回答。只是想确定......所以如果newDeposit.await 释放锁并且一旦Withdraw 获得锁newDeposit.signal 会做什么......它是否也会释放通过存款获得的锁并让它撤回(如果是这样,withdraw 中的其余代码不应像 finally 块中的 print 语句那样正确执行)或者它会执行其他操作。?
    • @Badri,注意await() 不会简单地释放锁。它释放锁,等待通知,然后等待(如果需要)重新获取锁。锁总是会在await() 返回之前重新上锁。
    猜你喜欢
    • 2013-07-12
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 2019-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多