Do Android ART и HotSpot ведут себя по-разному в энергонезависимой переменной видимости? - PullRequest
1 голос
/ 09 апреля 2020

Я тестировал приведенный ниже фрагмент кода на HotSpot и Android ART, но с разными результатами.

На HotSpot, MyThread никогда не получает обновленный isRunning, он получает isRunning = true всегда ... Но когда я проверяю его на ART, MyThread может получить обновленный isRunning и выйти из l oop нормально ...

Как я знаю о java правило "происходит раньше", энергонезависимый не виден в многопоточности, так же, как поведение кода ниже в Hotspot.

Зависит ли это от реализации виртуальной машины? А может, у Android ART есть своя оптимизация?

class MyThread extends Thread {
    public boolean isRunning = true;

    @Override
    public void run() {
        System.out.println("MyThread running");
        while (true) {
            if (isRunning == false) break;
        }
        System.out.println("MyThread exit");
    }
}

public class RunThread{
    public static void main(String[] args) {
        new RunThread().runMain();
    }

    public void runMain() {
        MyThread thread = new MyThread();
        try {
            thread.start();
            Thread.sleep(500);
            thread.isRunning = false;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

1 Ответ

0 голосов
/ 09 апреля 2020

энергонезависимый не виден в многопоточности, так же, как поведение кода ниже в Hotspot.

Это не совсем верно. Энергонезависимая запись, без какой-либо дополнительной синхронизации или других отношений «происходит до», не гарантируется для чтения этой же переменной в другом потоке. Это позволило быть видимым, хотя. Я абсолютно видел, как HotSpot делает записи видимыми между потоками, несмотря на то, что ничего не произошло до того. Основываясь на моем опыте с этим, я подозреваю, что если вы удалите этот вызов Thread.sleep в своем коде, HotSpot также сделает запись в isRunning видимой для потока, несмотря на отсутствие каких-либо отношений, происходящих перед записью между записью и чтение.

Вы определенно правы, что это VM-специфицировано c, и, возможно, даже вероятно процессорная спецификация c, так как разные архитектуры могут давать разное количество синхронизации для "бесплатно" или иметь разные объемы кеша, которые влияют на то, будет ли адрес памяти считываться из кеша ядра или извлекаться из основной памяти.

Таким образом, вы никогда не должны полагаться на такое поведение, работающее любым конкретным c способом. на любой указанной c ВМ - она ​​может быть изменена без предупреждения.

...