ReentrantLock:为什么lock.unlock()不释放锁?

时间:2019-06-21 21:04:56

标签: java concurrency locking

我的任务是实现实时锁定。我已经创建了简单的应用程序。看来效果很好。下一个任务是开发应用程序,从而确定了活锁问题。为此,我计划在代码中输入一个随机值的变量。但是首先,我在BankAccount#tryTransfer(...)中注意到了一些意外的情况。代码字符串this.lock.unlock();(在Thread.sleep(3_000);之前)不会释放锁。为什么?有什么帮助吗?预先感谢!

BankAccount.java:

package com.example.livelock;

import java.util.concurrent.locks.*;

public class BankAccount {

    private int id;
    private double balance;
    private Lock lock = new ReentrantLock();

    public BankAccount(int id, double balance) {
        this.id = id;
        this.balance = balance;
    }

    private boolean decreaseMoney(double amount) throws InterruptedException {
        if(lock.tryLock()){
            Thread.sleep(500);
            balance = balance - amount;
            return true;
        }
        return false;
    }

    private boolean increaseMoney(double amount) throws InterruptedException {
        if(lock.tryLock()){
            Thread.sleep(500);
            balance = balance + amount;
            return true;
        }
        return false;
    }

    public void tryTransfer(BankAccount toAccount, double amount) throws InterruptedException {
        while(true){
            if(this.decreaseMoney(amount)){
                if(!toAccount.increaseMoney(amount)){
                    this.increaseMoney(amount);
                    this.lock.unlock();
                    Thread.sleep(3_000);
                    System.out.println(Thread.currentThread().getName() + " is trying to perform transaction, while " + this.lock.toString().replace("java.util.concurrent.locks.", "") + " | " + toAccount.lock.toString().replace("java.util.concurrent.locks.", ""));
                    continue;
                }
                toAccount.unlock();
                this.lock.unlock();
                break;
            }
        }
    }

    public void unlock(){
        lock.unlock();
    }
}

Transaction.java:

package com.example.livelock;

public class Transaction extends Thread {

    private BankAccount fromAccount;
    private BankAccount toAccount;
    private double amount;

    public Transaction(String name, BankAccount fromAccount, BankAccount toAccount, double amount) {
        super(name);
        this.fromAccount = fromAccount;
        this.toAccount = toAccount;
        this.amount = amount;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " has started");
        try {
            fromAccount.tryTransfer(toAccount, 10);
            System.out.println(name + ": money is transfered");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name + " has finished");
    }
}

Tester.java:

package com.example.livelock;

public class Tester {

    public static void main(String[] args) throws InterruptedException {

        String name = Thread. currentThread().getName();
        System.out.println(name + " has started");

        BankAccount account1 = new BankAccount(1, 100);
        BankAccount account2 = new BankAccount(2, 100);

        Transaction th1 = new Transaction("thread-1", account1, account2, 10);
        Transaction th2 = new Transaction("thread-2", account2, account1, 10);

        th1.start();
        th2.start();

        Thread.sleep(30_000);

        System.out.println(name + " has finished");
    }
}

0 个答案:

没有答案