Как гарантировать потокобезопасность для 2 последовательных операторов в Java? - PullRequest
0 голосов
/ 07 января 2019

Этот смоделированный банковский перевод функционирует, как показано ниже, используя ReentrantLock.newCondition ():

class Bank {
    private Lock bankLock = new ReentrantLock();
    private Condition sufficientFunds = bankLock.newCondition();
    private final double[] accounts;

    public Bank(int n, double initialBalance) {
        accounts = new double[n];
        Arrays.fill(accounts, initialBalance);
    }

    public void transfer(int from, int to, double amount) throws InterruptedException {
        bankLock.lock();
        try {
            while(accounts[from] < amount) {
                sufficientFunds.await();
            }
            System.out.println(Thread.currentThread());
            accounts[from] -= amount;//risky
            // What if interrupted here ??????
            accounts[to] += amount;  //risky
            sufficientFunds.signalAll();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            bankLock.unlock();
        }
    }

Это выглядит нормально, поскольку это обычный пример использования условия для синхронизации потока, блокировка всегда будет "разблокирована" при прерывании потока.

Но в случае, если этот поток прерывается в местах между

accounts[from] -= amount;//risky

и

accounts[to] += amount;  //risky

Тогда общая сумма в банке не будет остатками на всех! И я думаю, что объявление «учетных записей» атомным массивом не решает проблему. Я думаю, что проблема заключается в том, что я должен заработать «+ деньги» и «- деньги» внутри транзакции, либо как успешный, так и должен быть откат.

Так есть ли в java параллельной библиотеке удобный способ для выполнения этой "транзакции"? Или для этого нужен какой-то особый дизайн, и как его реализовать?

Большое спасибо.

1 Ответ

0 голосов
/ 07 января 2019

Прерывание протектора не может произойти в случайной точке.

Если кто-то позвонит Thread.interrupt, это не остановит поток немедленно.

ThreadInterruptException будет вызываться только из методов, которые его объявляют.

Так что если вы не вызываете такой метод из своего кода, проблем не будет.

...