Может ли кто-нибудь объяснить мне, какие преимущества и недостатки двух разных подходов?Java, похоже, поддерживает нестабильные поля типа long, а C# - нет. Каковы причины этого?
ответ
Когда double
или long
в Java - volatile
, §17.7 of the Java Language Specification требует, чтобы данные были прочитаны и записаны атомарно. Когда они нестабильны, они могут быть записаны в нескольких операциях. Это может привести, например, к верхним 32 битам длинного, содержащему новое значение, тогда как нижние 32 бита все еще содержат старое значение.
Атомные считывания и записи для программиста проще продумать и написать правильный код. Однако поддержка атомных операций может наложить нагрузку на разработчиков VM в некоторых средах.
Я предполагаю, что это сводится к тому, что может гарантировать модель памяти. Я не знаю огромной суммы о модели памяти CLI (что C# должен использовать), но я знаю, что это будет гарантировать 32 бита ... но не 64 (хотя это будет гарантировать 64-битную ссылку на x64 - полные правила приведены в §17.4.3 ECMA 334v4). Так что это не может быть volatile
. У вас все еще есть методы Interlocked
(например, long Interlocked.Exchange(ref long,long)
и long Interlocked.Increment(ref long)
и т. Д.).
Я предполагаю, что долговечность не может быть изменчивой в C#, потому что они больше 32 бит и не могут быть доступны в атомной операции. Несмотря на то, что они не будут храниться в регистре или кэше ЦП, поскольку для чтения или записи значения требуется несколько операций, один поток может прочитать значение, а другой - в процессе его записи.
Я считаю, что существует разница между тем, как Java реализует изменчивые поля и как работает DotNet, но я не уверен в деталях. Java может использовать блокировку в поле, чтобы предотвратить проблему, с которой имеет C#.
Я не знаю, почему volatile не может быть применен к 64-битным ints в C#, но вы можете использовать Thread.VolatileWrite, чтобы делать то, что вы хотите на C#. Ключевое слово volatile - это просто синтаксический сахар на этом вызове.
выдержка:
Примечание: В C#, используя летучий модификатор на поле гарантирует, что доступ к этой области использует Thread.VolatileRead или Thread.VolatileWrite.
Синтаксический сахар (ключевое слово) применяется к 32-битным ints, но вы можете использовать фактические вызовы методов в 64-битных ints.
Тем не менее, странно, что код не позволит вам указывать волатильное 64-битовое поле, если вы также укажете платформу как x64. –
CLI должен работать независимо от базовой платформы, поэтому он не хочет делать обещания, которые зависят от того, на чем вы работаете. –