Java, похоже, поддерживает изменчивые поля типа long, а С# - нет. Каковы причины этого?

Может ли кто-нибудь объяснить мне, какие преимущества и недостатки двух разных подходов?

Ответ 1

Когда a double или long в Java volatile, & sect; 17.7 Спецификации Java Language требует, чтобы они считываются и записываются атомарно. Когда они нестабильны, они могут быть записаны в нескольких операциях. Это может привести, например, к верхним 32 битам длинного, содержащему новое значение, тогда как нижние 32 бита все еще содержат старое значение.

Атомные чтения и записи проще программисту рассуждать и писать правильный код. Тем не менее, поддержка атомных операций может наложить нагрузку на разработчиков ВМ в некоторых средах.

Ответ 2

Я не знаю, почему volatile не может применяться к 64-битным ints в С#, но вы можете использовать Thread.VolatileWrite для сделайте то, что вы хотите на С#. Ключевое слово volatile - это просто синтаксический сахар на этом вызове.

выдержка:

Примечание: В С# использование изменчивого модификатора в поле гарантирует, что весь доступ к этому полю использует Thread.VolatileRead или Thread.VolatileWrite.

Синтаксический сахар (ключевое слово) применяется к 32-битным ints, но вы можете использовать фактические вызовы методов для 64-битных ints.

Ответ 3

Я предполагаю, что это сводится к тому, что может гарантировать модель памяти. Я не знаю огромной суммы о модели памяти CLI (что С# должен использовать), но я знаю, что это будет гарантировать 32 бита... но не 64 (хотя это будет гарантировать 64-битную ссылку на x64 - полные правила приведены в §17.4.3 ECMA 334v4). Так что это не может быть volatile. У вас все еще есть методы Interlocked (например, long Interlocked.Exchange(ref long,long) и long Interlocked.Increment(ref long) и т.д.).

Ответ 4

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

Я считаю, что существует разница между тем, как Java реализует изменчивые поля и как работает DotNet, но я не уверен в деталях. Java может использовать блокировку в поле, чтобы предотвратить проблему, с которой имеет С#.