![]() |
VOOZH | about |
volatile keyword in C++ is used to declare variables that can be modified by external factors outside the program's control. This qualifier informs the compiler that the variable's value may change anytime, preventing certain optimizations that could lead to unexpected behavior. In this article, we will learn about the volatile qualifier and its usage in various scenarios.
Table of Content
In C++ the volatile keyword is used to declare a variable whose value can be changed by various external factors that are outside the program's control, such as hardware or a concurrently executing thread. This prevents the compiler from doing some optimizations assuming the variable value remains unchanged unless explicitly changed within the program. Following is the syntax to use the volatile keyword in C++.
volatile type variable_Name;Here,
Volatile variables within a function is very useful when we deal with hardware registers or shared memory in a multithreaded environment and handle concurrent operations. Volatile variables helps to maintain data consistency and also ensures that the compiler doesn't waste the computer power in optimizations for the variables as the value of the variable can change any time.
Example
The following program demonstrates the implementation of the above concept in C++.
Output
Working...
Working...
Working...
Interrupt received. Exiting.
Explanation: In the above program, the interruptFlag is declared volatile because it is shared between the main thread and the worker thread and it's value can change anytime. The volatile qualifier ensures that the worker thread always reads the most up to date value of the interruptFlag even if the compiler optimizes the read operation.
Volatile variables are used within a class when a class represents an hardware interface or when we deal with shared data in the multithreaded environments.
Example
The following program demonstrates the implementation of the above concept in C++.
Output
Current temperature: 86°C
Current temperature: 77°C
Current temperature: 15°C
Current temperature: 93°C
Explanation: In the above program the temperature member variable of the class sensorInterface is declared volatile because it is updated in a separate thread. The volatile keyword will ensure that everytime getTemperature() function is called, it reads the latest value from the memory rather than using a cached value stored by the compiler for optimizations.
Just like variables the value represented by the pointers can also change unexpectedly or there can be scenarios where the pointers points to a volatile data. In such scenarios, it is recommended to use volatile pointers so that the pointers always points to the most recent value of the data. Following is the syntax to use volatile pointers in C++.
There are 3 ways to declare volatile pointers in C++:
1. Pointer to volatile variable
volatile data_type* ptr = & volatile_variable.2. Volatile pointer to non volatile data
data_type* volatile = &variable_name3. Volatile pointer to volatile data
volatile data_type* volatile ptr = &volatile_variableHere,
The following program demonstrates the implementation of the above concept in C++.
volatile_var: 30 regular_var: 40 volatile_var: 50
Explanation: The following program demonstrates the three ways of using volatile pointers. ptr_to_volatile ensures that the data it points to is always read from memory. volatile_ptr ensures that the pointer itself is always read from memory. volatile_ptr_to_volatile combines both effects, ensuring that both the pointer and the data it points to are always read from memory and gets the most recent value not the cached value stored by the compiler for optimization.
We can also declare the member functions within a class as volatile so that the compiler does not optimize the function calls away. The volatile member functions indicates that the function may be called on volatile objects and doesn't modify the object state.
The following program demonstrates the implementation of the above concept in C++.
Output
Final count: 2000000Explanation: In the above example, the increment() and the getvalue() functions are declared as volatile member functions. This allows them to be called on volatile objects from the safeCounter class. The volatile qualifier on these functions ensures that they always work with the most up-to-date value of count, even in a multithreaded environment.
In a multithreaded environment when multiple threads access a shared variable concurrently, there's a potential risk of race conditions and data inconsistencies. By declaring shared variables to be volatile, we can ensure that each thread reads the most recent value from memory and writes it from other threads immediately.
The following program demonstrates the use of volatile qualifier in a multithreaded environment.
Output
Producer: Data produced.
Consumer: Data consumed.
Main: All threads have finished execution.
Time Complexity: O(1)
Auxiliary Space: O(1)
Explanation: The above program is a solution of classical synchronization problem known as the producer consumer problem. In this program, volatile qualifier bool data_ready ensures that the consumer thread reliably observes changes made by the producer thread to data_ready variable. This prevents compiler optimizations that could lead to stale reads, highlighting volatile's crucial role in maintaining synchronization and correct behavior in multithreaded environments.
Following are some common applications of the volatile qualifier: