package threaddemo.dataracing;

import java.util.concurrent.atomic.AtomicInteger;

public class CASByAtomicInteger {
    private final AtomicInteger counter = new AtomicInteger(0);

    // for aba problem
    private final AtomicInteger unSafeCounter = new AtomicInteger(0);

    public static void main(String[] args) {
        CASByAtomicInteger casByAtomicInteger = new CASByAtomicInteger();
        casByAtomicInteger.safeIncrementDemo();
        System.out.println("-------------------------");
        casByAtomicInteger.unsafeIncrementDemo();
    }
    public void safeIncrementDemo() {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                counter.incrementAndGet();
            }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                counter.incrementAndGet();
            }
        });

        t1.start();
        t2.start();
        try {
            t1.join();
            t2.join();
            System.out.println(STR."counter: \{counter.get()}");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void unsafeIncrementDemo() {
        Thread t1 = new Thread(() -> {
            int initValue = unSafeCounter.get();
            System.out.println(STR."Thread 1: Initial value = \{initValue}");
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            unSafeCounter.compareAndSet(0,20);
            unSafeCounter.compareAndSet(20,0);

            System.out.println(STR."Thread 1: Final value = \{unSafeCounter.get()}");

        },"t1");

        Thread t2 = new Thread(() -> {
            int value = unSafeCounter.get();
            System.out.println("Thread 2: Initial value = " + value);
            try {
                // 等待线程1完成 ABA 操作
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // 尝试 CAS 操作
            boolean success = unSafeCounter.compareAndSet(0, 30); // A -> C
            System.out.println(STR."Thread 2: CAS success = \{success}");
            System.out.println(STR."Thread 2: Final value = \{unSafeCounter.get()}");
        },"t2");

        t1.start();
        t2.start();

        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
