Volatile (computer programming): Difference between revisions

Content deleted Content added
Adding another cite from the same authors regarding how most C/C++ compilers have buggy volatile behavior
Link suggestions feature: 2 links added.
 
(12 intermediate revisions by 8 users not shown)
Line 1:
{{Short description|A keywordKeyword used in some programming languages to tag variables}}
{{Lowercase title}}
In [[computer programming]], a [[Variable (computer science)|variable]] is said to be '''''volatile''''' if its [[Value (computer science)|value]] is a value that can be asynchronously read byor something else ormodified asynchronously changed by something elseother whilethan the current code[[thread is(computing)|thread runningof execution]].
The value of a <code>volatile</code> variable may spontaneously change for reasons such as:
 
sharing values with other threads;
Despite being a common keyword across many programming languages, the behavior of the <code>volatile</code> keyword differs in subtle and important ways between the several programming languages that have it. The common theme is that a <code>volatile</code> variable is a variable that may be read or modified by something outside of the current [[thread (computing)|thread of execution]] while the current [[thread (computing)|thread]] is running. In particular, the value of a <code>volatile</code> variable may spontaneously change without any possible cause from the code in the current [[thread (computing)|thread]], and sometimes a <code>volatile</code> variable may spontaneously change without any possible cause from any code in the whole program. The typical reasons to use <code>volatile</code> include: accessing hardware devices via [[memory-mapped I/O]] (where you can send and receive messages from [[peripheral device]]s by reading from and writing to memory), sharing values with asynchronous signal handlers, and sharing values with other [[thread (computing)|threads of execution]]. Support for these use cases varies considerably among the several programming language that have the <code>volatile</code> keyword.
sharing values with asynchronous [[signal handler]]s;
 
accessing hardware devices via [[memory-mapped I/O]] (where you can send and receive messages from [[peripheral device]]s by reading from and writing to memory).
Support for these use cases varies considerably among the programming languages that have the <code>volatile</code> keyword.
Volatility can have implications regarding function [[calling convention]]s and how variables are stored, accessed and cached.
 
Line 20 ⟶ 22:
The C and C++ standards allow writing portable code that shares values across a <code>[[setjmp|longjmp]]</code> in <code>volatile</code> objects, and the standards allow writing portable code that shares values between signal handlers and the rest of the code in <code>volatile</code> <code>sig_atomic_t</code> objects. Any other use of <code>volatile</code> keyword in C and C++ is inherently non-portable or incorrect. In particular, writing code with the <code>volatile</code> keyword for [[memory-mapped I/O]] devices is inherently non-portable and always requires deep knowledge of the specific target C/C++ implementation and platform.
 
=== Multi-Threadingthreading ===
It is a common misconception that the <code>volatile</code> keyword is useful in 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 onThe <code>volatile</code> variableskeyword 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 |date=21 September 2021 |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> MostUnlike the [[Java (programming language)|Java]] and [[C Sharp (programming language)|C#]] programming languages, operations on <code>volatile</code> variables in C and C++ compilers,are linkersnot [[atomic operation|atomic]], and runtimesoperations simplyon <code>volatile</code> variables do not providehave thesufficient necessary[[memory ordering]] guarantees (such asi.e. [[memory barrier|memory barriers]]). Most C and C++ compilers, linkers, and runtimes simply do not provide the necessary memory ordering guarantees 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. With the modern C11 and C++11 standards, programmers can write portable [[thread (computing)|multi-threading]] code using new portable constructs such as the <code>std::atomic<T></code> templates.<ref>{{cite web |title=volatile (C++) |url=https://msdn.microsoft.com/en-us/library/12a04hfd.aspx |work=Microsoft MSDN|date=21 September 2021 }}</ref>
 
===Example of memory-mapped I/O in C===
Line 209 ⟶ 211:
|}
 
=== Standards Defectsdefects ===
While intended by both C and C++, the current C standard fails 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>
 
=== Compiler Defectsdefects ===
Unlike other language features of C and C++, the <code>volatile</code> keyword is not well supported by most C/C++ implementations - even for portable uses according to the C and C++ standards. Most C/C++ implementations are buggy regarding the behavior of the <code>volatile</code> keyword.<ref>{{Cite journal |lastlast1=Eide |firstfirst1=Eric |last2=Regehr |first2=John |date=Oct.October 2008 |title=Volatiles Are Miscompiled, and What to Do about It |url=https://users.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf |journal=Proceedings of the Eighth ACM and IEEE International Conference on Embedded Software (EMSOFT), Atlanta, Georgia, USA |via=cs.utah.edu}}</ref><ref>{{Cite web |title=Volatile Bugs, Three Years Later – Embedded in Academia |url=https://blog.regehr.org/archives/503 |access-date=2024-08-28 |website=blog.regehr.org}}</ref> Programmers should take great care whenever using the <code>volatile</code> keyword in C and C++.
and IEEE International Conference on Embedded Software (EMSOFT),
Atlanta, Georgia, USA, |via=cs.utah.edu}}</ref><ref>{{Cite web |title=Volatile Bugs, Three Years Later – Embedded in Academia |url=https://blog.regehr.org/archives/503 |access-date=2024-08-28 |website=blog.regehr.org}}</ref> Programmers should take great care whenever using the <code>volatile</code> keyword in C and C++.
 
==In Java==
Line 221:
 
* <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> read will read the current value, (and it will not reada an older valuepast or afuture value the future), and all <code>volatile</code> reads will agree on a single global order of <code>volatile</code> writes.
* <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 provides 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>
 
=== VeryEarly Oldversions Versions Ofof 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.