В Java, как очистить кэш памяти процессора, чтобы он извлекал последние данные из оперативной памяти? - PullRequest
2 голосов
/ 06 марта 2012

Компьютер имеет оперативную память, но также имеет небольшой, более быстрый кэш-память процессора.Модель памяти Java гарантирует, что кэш памяти ЦП сбрасывается при доступе к переменной с volatile, но, поскольку мы используем эту переменную в одном классе только в одном потоке, сомнительно, что JIT не просто оптимизирует еепрочь.

Чтобы диагностировать ошибку (которая проявляется только тогда, когда мы вызываем Thread.sleep () достаточно долго в определенной точке), мы должны иметь возможность сделать что-то подобное (вместо sleep ()):

System.clearCpuCache();

Какой самый простой и надежный способ реализации такого метода? Он должен гарантировать, что он не будет оптимизировать JIT без очистки кеша.Мы можем воспроизвести нашу ошибку только с включенным JIT, поэтому отключение JIT не вариант.

Ответы [ 4 ]

8 голосов
/ 06 марта 2012

Вы вообще не можете. За исключением производительности, наличие кеша прозрачно для приложений. Это относится и к многопроцессорным системам, если кеш-система «когерентна», что сегодня используется практически всеми платформами.

Таким образом, ваша ошибка лежит в другом месте.

Такие вещи, как энергозависимые и синхронизированные блоки, сами по себе не влияют на когерентность кэша, а скорее оптимизируют регистр, используют атомарные инструкции (в том числе, скажем, очищают буфер хранилища, который отличается от кэша!), И скоро. Это то, на что вы должны обратить внимание (ну, учитывая отсутствие подробностей в вашем описании, трудно сказать, но как первое предположение ...), а не пытаться очистить кэш.

1 голос
/ 23 марта 2012

Вы пробовали с AtomicInteger ?

Я не вижу, как можно получить неверную версию volatile int из кэша процессора, если значение всегда изменяется / читается одним и тем же потоком. Может быть, попытаться распечатать, какой поток активен при каждом чтении / записи переменной, просто чтобы быть уверенным на 100%:

System.out.println(Thread.currentThread().getName());
1 голос
/ 06 марта 2012

Я не уверен, что это так (здесь требуется больше подробностей!), Но следует помнить одну вещь, если вы видите жесткую ошибку в многопоточности, связанную с volatile, это то, что volatile не обязательно атомарна.

т.е. вы можете подумать, что вы обновили изменчивую переменную и что новое значение должно быть видно, но на самом деле это не так, потому что полное обновление еще не завершено.

http://www.ibm.com/developerworks/java/library/j-jtp11234/

1 голос
/ 06 марта 2012

Доступ к переменной volatile должен обходить кеш, а не сбрасывать его.Таким образом, очистка кэша не должна влиять на поведение volatile.Как ошибка проявляется?Вы видите устаревшее значение после Thread.sleep () и в том же потоке?Много лет назад я написал тесты для Java Compatibility Test Suite.Один из этих тестов доказал, что переменную volatile можно читать из кеша, а не из основной памяти.Интересно, если эта ошибка все еще существует.Пожалуйста, пришлите мне подробности на rfq (at) list.ru, я постараюсь создать убедительный тест.

...