package dev.elaine.concurrency;

import java.util.concurrent.locks.ReentrantLock;

public final class DeterministicTransferSample {
    private DeterministicTransferSample() {
    }

    static final class Account {
        private final long id;
        private final ReentrantLock lock = new ReentrantLock();
        private long cents;

        Account(long id, long cents) {
            this.id = id;
            this.cents = cents;
        }
    }

    public static void transfer(Account source, Account target, long cents) {
        Account first = source.id < target.id ? source : target;
        Account second = source.id < target.id ? target : source;
        first.lock.lock();
        try {
            second.lock.lock();
            try {
                if (cents < 0 || source.cents < cents) {
                    throw new IllegalArgumentException("转账金额非法或余额不足");
                }
                source.cents -= cents;
                target.cents += cents;
            } finally {
                second.lock.unlock();
            }
        } finally {
            first.lock.unlock();
        }
    }

    static long totalCents(Account first, Account second) {
        return first.cents + second.cents;
    }

    public static void main(String[] args) throws InterruptedException {
        Account first = new Account(1, 10_000);
        Account second = new Account(2, 10_000);
        Thread forward = Thread.ofPlatform().start(() -> transfer(first, second, 1_000));
        Thread backward = Thread.ofPlatform().start(() -> transfer(second, first, 500));
        forward.join();
        backward.join();
        System.out.println("总金额=" + totalCents(first, second));
    }
}
