Content deleted Content added
Slight rewrite in C/C++ multi-threading to emphasize that to be a useful threading construct in most cases, it must offer atomic semantics and also memory ordering guarantees. Atomic does not imply memory ordering e.g. fences, and fences do not imply atomic. Not-atomic simply means that you might observe word tearing. You need fences on top of avoiding word-tearing to be a useful threading construct in most cases. |
CortexFiend (talk | contribs) Link suggestions feature: 2 links added. |
||
(8 intermediate revisions by 5 users not shown) | |||
Line 1:
{{Short description|
{{Lowercase title}}
In [[computer programming]], a [[Variable (computer science)|variable]] is said to be '''''volatile''''' if its [[Value (computer science)|value]]
The value of a <code>volatile</code> variable may spontaneously change for reasons such as:
sharing values with other threads;
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-
It is a common misconception that the <code>volatile</code> keyword is useful in portable [[thread (computing)|multi-threading]] code in C and C++. The <code>volatile</code> keyword in C and C++ 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> 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]], and operations on <code>volatile</code> variables do not have sufficient [[memory ordering]] guarantees (i.e. [[memory barrier|memory barriers]]). Most C and C++ compilers, linkers, and runtimes simply do not provide
===Example of memory-mapped I/O in C===
Line 209 ⟶ 211:
|}
=== Standards
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
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 |last1=Eide |first1=Eric |last2=Regehr |first2=John |date=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++.
Line 221 ⟶ 223:
* 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 not a past or future value), 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>
===
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.
|