2014-12-25 2 views
15

В соответствии с моделью памяти Java инструкции могут быть переупорядочены до тех пор, пока выполняется well-formed.Является ли переупорядочение Java влияющим на System.currentTimeMillis()?

Так что, интересно, возможно ли, что следующие коды выдают следующий результат?

[коды] [в том же потоке]

long a = System.currentTimeMillis(); 
long b = System.currentTimeMillis(); 
long c = System.currentTimeMillis(); 

[выход]

a == 10, b == 20, c == 15 

Если не возможно, то, что делает JVM/реализаций сделать, чтобы предотвратить это ?

+0

Если вы не запустите это в системе с установленными часами, очень близкими к 1 января 1970 года, вы, вероятно, не получите этих точных значений. Почему JVM переупорядочивает эти инструкции? –

+0

@ElliottFrisch привет. Эти точные значения используются для иллюстрации того, что a, b и c не могут монотонно возрастать; не должно быть 10, 20 и 15 :-P –

+0

@ElliottFrisch Что я здесь делаю, есть ли гарантия того, что эти 3 System.currentTimeMillis() не будут переупорядочены JVM? –

ответ

5

См. Этот вопрос Instruction reordering & happens-before relationship in java.

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

+0

Джозеф, спасибо за ваш быстрый ответ. Тем не менее, я склонен полагать, что эти 3 инструкции могут быть выполнены не по порядку, потому что методы вызова не являются ДЕЙСТВИЯми, определенными моделью памяти Java, тогда не происходит - до того, как отношения существуют для этих 3-х инструкций. Если int a = 1 + 1, int b = 2 + 2 в одном потоке может быть переупорядочено и исполнено как int b = 2 + 2, int a = 1 + 1, то в чем особенность System.currentTimeMillis(), которая делает их обязательными для исполнения? –

+0

На практике «currentTimeMillis» является либо «внешним вызовом», поэтому я не знаю, что он делает, и я не буду его переупорядочивать ». В противном случае предположим, что переопределитель знает, как это работает, если этот метод будет реализован исключительно в java, ему придется прочитать некоторую изменчивую переменную (системные часы). В любом случае, его не следует переупорядочивать. – Sebi

+0

@ Sebi, мне нравится ваш вывод; любая ссылка может это доказать? –

1

Из-за системного вызова пользователя компиляторы не должны переупорядочивать их в одном потоке. Если это было неверно, мы могли бы даже испытывать переупорядочивающие эффекты в System.out.println (независимые значения); Я предполагаю, что доступ к часам системы/ОС создает своего рода взаимосвязь между этими операциями (всегда для текущего потока), поэтому теоретически между ними существует какая-то зависимость. Вероятно, JVM рассматривает эту проблему и никогда не переупорядочивает вызовы системы пользователей.

+0

Кто говорит, что currentTimeMillis - системный вызов? Это деталь реализации. – usr

+0

Это деталь реализации да, но на самом деле текущая реализация не использует системные ресурсы? Если да, то это может быть подвергнуто цензуре с помощью JVM и позволяет избежать переупорядочения. Если реализация по умолчанию не включала системный вызов, то может быть иная. –

+0

Вы говорите, что вызов 'native' метода не может быть повторно заказан? –