Почему ReentrantLock не работает во время синхронизированной работы в демоверсии? - PullRequest
1 голос
/ 30 марта 2019

Я пытаюсь следовать примеру ReentrantLock в Java, Разница между синхронизированным и ReentrantLock учебным пособием.И у меня демонстрация началась с -ea как

public class ReentrantLockZero {
    private static ReentrantLock CountLock = new ReentrantLock();
    private static int count = 0;
    private static final int RESULT_COUNT = 10_000;

    public static void main(String... args) throws Exception {
        ThreadPoolExecutor threadPoolExecutor = getMyCachedThreadPool();
        for (int i = 0; i < RESULT_COUNT; ++i) {
            threadPoolExecutor.submit(ReentrantLockZero::getCount);
            threadPoolExecutor.submit(ReentrantLockZero::getCountUsingLock);
        }
        threadPoolExecutor.shutdown();
        threadPoolExecutor.awaitTermination(10, TimeUnit.SECONDS);
        assert count == RESULT_COUNT * 2;
    }

    private static synchronized int getCount() {
        count++;
        System.out.println(Thread.currentThread().getName() + " counting in synchronized: " + count);
        return count;
    }

    private static int getCountUsingLock() {
        CountLock.lock();
        try {
            count++;
            System.out.println(Thread.currentThread().getName() + " counting in lock: " + count);
            return count;
        } finally {
            CountLock.unlock();
        }
    }
}

При использовании ReentrantLock в качестве второго метода getCountUsingLock я получу java.lang.AssertionError, но когда я закомментировал их для использования synchronized это было бы хорошо.

Учитывая его Re entrantLock, я удалил CountLock, определенный в классе и использующий локальную блокировку, как указано ниже, но она все еще не работает.

private static int getCountUsingLock() {
    ReentrantLock countLock = new ReentrantLock();
    countLock.lock();
    try {
        count++;
        System.out.println(Thread.currentThread().getName() + " counting in lock: " + count);
        return count;
    } finally {
        countLock.unlock();
    }
}

Что здесь упущено?

Любая помощь будет оценена;)

1 Ответ

2 голосов
/ 30 марта 2019

Вид дурака из себя.

Это работает так, потому что я на самом деле блокирую разные объекты .

private static synchronized int getCount()

равно

private static synchronized (ReentrantLockZero.class) int getCount()

, в то время как new ReentrantLock(); всегда является новым объектом, и невозможно устранить условие гонки , используя различные блокировки.

Так глупо с моей стороны, это легко исправить с помощью следующих демонстраций

public class ReentrantLockZero {
    private static ReentrantLock CountLock = new ReentrantLock();
    private static int synchronisedCount = 0;
    private static int lockedCount = 0;
    private static final int RESULT_COUNT = 10_000;

    public static void main(String... args) throws Exception {
        ThreadPoolExecutor threadPoolExecutor = getMyCachedThreadPool();
        for (int i = 0; i < RESULT_COUNT; ++i) {
            threadPoolExecutor.submit(ReentrantLockZero::getSynchronisedCount);
            threadPoolExecutor.submit(ReentrantLockZero::getCountUsingLock);
        }
        threadPoolExecutor.shutdown();
        threadPoolExecutor.awaitTermination(10, TimeUnit.SECONDS);
        assert synchronisedCount == RESULT_COUNT;
        assert lockedCount == RESULT_COUNT;
    }

    private static synchronized int getSynchronisedCount() {
        synchronisedCount++;
        System.out.println(Thread.currentThread().getName() + " counting in synchronized: " + synchronisedCount);
        return synchronisedCount;
    }

    private static int getCountUsingLock() {
        CountLock.lock();
        try {
            lockedCount++;
            System.out.println(Thread.currentThread().getName() + " counting in lock: " + lockedCount);
            return lockedCount;
        } finally {
            CountLock.unlock();
        }
    }
}

Почему работает synchronized?Поскольку тогда существует только одна блокировка, оба метода блокируются, поэтому условие гонки решается напрямую.

Вид, который легко обмануть с помощью учебника;позор мне; (

...