Content deleted Content added
The removed part is not present in the referenced article and is incorrect |
Large cleanup. Fixed the introduction by mentioning that volatile is equally about reads as writes. Tried to clean up the introduction to be more accurate while still preserving the spirit of the volatile keyword in a way that is applicable to all programming languages. Also cleaned up the C/C++ and Java sections by removing unnecessary and duplicate information, and tried to make it flow better. Tags: references removed Visual edit |
||
Line 1:
{{Short description|A keyword used in some programming languages to tag variables}}
{{Lowercase title}}
In [[computer programming]], a '''volatile'''
Volatility can have implications regarding function [[calling convention]]s and how variables are stored, accessed and cached.
==In C and C++==
In C and C++, <code>volatile</code> is a [[type qualifier]], like <code>[[const (computer programming)|const]]</code>, and is a part of a [[data type|type]] (e.g. the type of a variable or field).
In C, and consequently C++, the <code>volatile</code> keyword was intended to:<ref name="auto">{{cite web |title=Publication on C++ standards committee|url= http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2016.html}}</ref>
Line 14 ⟶ 16:
*allow uses of <code>sig_atomic_t</code> variables in signal handlers.
Loosely, the <code>volatile</code> keyword tells a C/C++ [[optimizing compiler]] to not remove reads and writes (including seemingly redundant reads and writes), and to not introduce new reads and writes, and to not change the relative order of reads and writes. For example, the [[optimizing compiler]] cannot store a value written to a <code>volatile</code> variable in a register and then use that register for a later read of the same <code>volatile</code> variable. Instead, the compiler must flush the value to main memory for every write instruction in the code, and it must fetch the value from main memory for every read instruction in the code. These strict guarantees about preserving the exact number and order of reads and writes are required to write correct code to access [[memory-mapped I/O]] devices, to write correct code using <code>[[setjmp]]</code> and <code>longjmp</code>, and to write correct code that shares values with asynchronous signal handlers.
While intended by both C and C++, the C standards fail to express that the <code>volatile</code> semantics refer to the lvalue, not the referenced object. The respective defect report ''DR 476'' (to C11) is still under review with [[C17 (C standard revision)|C17]].<ref>[http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2244.htm ''Clarification Request Summary for C11.''] Version 1.13, October 2017.</ref>▼
=== Multi-Threading ===
It is a common misconception that the <code>volatile</code> keyword is useful for portable [[thread (computing)|multi-threading]] code in C and C++. Unlike the [[Java (programming language)|Java]] and [[C Sharp (programming language)|C#]] programming languages, operations on <code>volatile</code> variables in C and C++ are not [[atomic operation|atomic]]. The <code>volatile</code> keyword has ''never'' functioned as a useful, portable tool for ''any'' multi-threading scenario.<ref>{{cite web |title=Volatile Keyword In Visual C++ |url=http://msdn2.microsoft.com/en-us/library/12a04hfd.aspx |work=Microsoft MSDN}}</ref><ref>{{cite web |title=Linux Kernel Documentation – Why the "volatile" type class should not be used |url=https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html |work=kernel.org}}</ref><ref>{{cite web |author1=Scott Meyers |author2=Andrei Alexandrescu |year=2004 |title=C++ and the Perils of Double-Checked Locking |url=http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf |work=DDJ}}</ref><ref>{{cite web |author1=Jeremy Andrews |year=2007 |title=Linux: Volatile Superstition |url=http://kerneltrap.org/Linux/Volatile_Superstition |archive-url=https://web.archive.org/web/20100620121940/http://kerneltrap.org/Linux/Volatile_Superstition |archive-date=2010-06-20 |access-date=Jan 9, 2011 |publisher=kerneltrap.org}}</ref> Most C and C++ compilers, linkers, and runtimes simply do not provide the necessary guarantees (such as [[memory barrier|memory barriers]]) to make the <code>volatile</code> keyword useful for ''any'' multi-threading scenario. Before the C11 and C++11 standards, programmers were forced to rely on guarantees from the individual implementations and platforms (e.g. POSIX and WIN32) to write [[thread (computing)|multi-threading]] code. The C11 and C++11 standards introduced new constructs such as the <code>std::atomic<T></code> templates which allowed writing portable [[thread (computing)|multi-threading]] code.<ref>{{cite web |title=volatile (C++) |url=https://msdn.microsoft.com/en-us/library/12a04hfd.aspx |work=Microsoft MSDN}}</ref>
===Example of memory-mapped I/O in C===
Line 45 ⟶ 46:
</syntaxhighlight>
However, the programmer may make <code>foo</code>
To prevent the compiler from
<syntaxhighlight lang="c">
Line 60 ⟶ 61:
</syntaxhighlight>
===Optimization comparison in C===
Line 208 ⟶ 207:
|}
===
▲While intended by both C and C++, the current C
==In Java==
* <code>volatile</code> reads and writes are [[atomic operation|atomic]]. In particular, reads and writes to <code>long</code> and <code>double</code> fields will not tear. (The [[atomic operation|atomic]] guarantee applies only to the <code>volatile</code> primitive value or the <code>volatile</code> reference value, and ''not'' to any Object value.)
* There is a single global ordering of all <code>volatile</code> reads and writes. In other words, a <code>volatile</code> will read the current value. It will not read an older value, and it will not read a value from the future.
* <code>volatile</code> reads and writes have "acquire" and "release" [[memory barrier]] semantics (known in the Java standard as [[happened-before|happens-before]]).<ref>Section 17.4.4: Synchronization Order
{{cite web |year=2013 |title=The Java® Language Specification, Java SE 7 Edition |url=http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4.4 |access-date=2013-05-12 |publisher=[[Oracle Corporation]]}}</ref><ref>{{cite web |date=2021-03-08 |title=Java Concurrency: Understanding the 'Volatile' Keyword |url=https://dzone.com/articles/java-concurrency-understanding-the-volatile-keyword |archive-url=https://web.archive.org/web/20210509104459/https://dzone.com/articles/java-concurrency-understanding-the-volatile-keyword |archive-date=2021-05-09 |access-date=2021-05-09 |publisher=dzone.com}}</ref> In other words, <code>volatile</code> provides guarantees about the relative order of <code>volatile</code> and non-<code>volatile</code> reads and writes. In other words, <code>volatile</code> basically the same memory visibility guarantees as a Java [[lock (computer science)|synchronized block]] (but without the mutual exclusion guarantees of a [[lock (computer science)|synchronized block]]).
Together, these guarantees make <code>volatile</code> into a useful [[thread (computing)|multi-threading]] construct in [[Java programming language|Java]]. In particular, the typical [[double-checked locking]] algorithm with <code>volatile</code> works correctly in [[Java programming language|Java]].<ref>{{cite web |author1=Neil Coffey |title=Double-checked Locking (DCL) and how to fix it |url=http://www.javamex.com/tutorials/double_checked_locking_fixing.shtml |access-date=2009-09-19 |publisher=Javamex}}</ref>
=== Very Old Versions Of Java ===
Before Java version 5, the Java standard did not guarantee the relative ordering of <code>volatile</code> and non-<code>volatile</code> reads and writes. In other words, <code>volatile</code> did not have "acquire" and "release" [[memory barrier]] semantics. This greatly limited its use as a [[thread (computing)|multi-threading]] construct. In particular, the typical [[double-checked locking]] algorithm with <code>volatile</code> did ''not'' work correctly.
==In C#==
|