Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What are the ways to use Volatile in C #

2025-04-05 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces the relevant knowledge of "what is the use of Volatile in C#". In the operation of actual cases, many people will encounter such a dilemma, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!

1.Overview

Friends who often study the .NET source code library will often see a keyword volatile, so what is its role in development?

Let's take a look at how it is described in the official document, as follows:

"the volatile keyword indicates that a field can be modified by multiple threads executing simultaneously. For performance reasons, compilers, runtime systems, and even hardware may rearrange reads and writes to memory locations. Fields declared as volatile will be excluded from some types of optimizations. It is not guaranteed that all volatile writes are sorted in the order in which they are executed from all threads of execution as a whole."

This article will focus on this part of the interpretation.

The declaration syntax is as follows:

Class VolatileTest {public volatile int sharedStorage; public void Test (int I) {sharedStorage = I;}} 2.Detail

Let's take a look at the pre-knowledge points.

(1) sbyte, byte, short, ushort, int, uint, char, float and bool will be used in CLR. And the reference type ensures that all bytes in the atomic (long, double are not atomic read and write) variables are written or read at once.

(2) Framework Class Library (FCL) ensures that all static methods are thread safe. This means that if two threads call a static method at the same time, no data will be corrupted. Why?

Public static string Print (String str) {string val = ""; val + = str; return val;}

Because of the variables declared in the static method, each thread will create a new one when it is called, instead of sharing a storage unit. For example, in the val here, each thread creates its own copy, so there are no thread safety issues. Note: static variables, because they occupy a storage area when the class is loaded, are shared by every thread, so if static variables are used in static methods, there will be thread safety issues.

(3) memory, CPU cache (Note: the following is a brief description, but not only that)

CPU cache, CPU integrated cache.

Memory, storage space provided by memory strip hardware.

Let's get back to the main point and use the following code examples to express the role of volatile.

Public class Program {public static int bookNum = 0; public static void Main (string [] args) {Console.WriteLine ("number of juster books:" + bookNum); Thread juster = new Thread (() = > {Console.WriteLine ("juster does not have books, waiting for parents to deliver books to school.") While (bookNum = = 0) {} Console.WriteLine ("juster gets the book and starts class.") ;}); juster.Name = nameof (juster); juster.Start (); Thread parent = new Thread () = > {Console.WriteLine ("parent is looking for a book in the house."); Thread.Sleep (2000); Console.WriteLine ("after parent finds the book, send it to school.") SendBook (); parent.Name = nameof (parent); parent.Start ();} public static void SendBook () {bookNum = 1;}}

The code execution output is as follows:

It's weird at this time, and according to the normal code execution logic, it's not hard to see that when the parent thread executes Sendbook (), juster should be able to get the book for class. But why didn't juster get it here?

Careful friends should have observed that the running mode here is Release, and it is well known that the release version of Release is .net will be more efficient than the Debug version.

Why is the Release version efficient? How did you get it? The following code explains:

In the decompiled diagram above, it is not difficult to see that the code of 10: 10-100 is compiled directly into 0. This is because the compiler optimizes the code when Release compiles. This is the most intuitive 'optimization' effect, in fact, the C # compiler converts your code into an intermediate language (IL). JIT then converts the IL into native CPU instructions. In addition, the C # compiler, the JIT compiler, and even CPU itself can optimize your code.

But in fact, in the above code, the value of count is always 0; so the loop never executes, and there is no need to compile the code within the loop to be 'optimized' after compilation. Having said all this, I just want to prove to everyone that there is' optimization'in the layer of Release compilation; let's go back to volatile.

Speaking of which, how to solve the problems caused by various' optimization'? At this point, you just need to prefix the booknum with the volatile keyword.

Public class Program {public static volatile int bookNum = 0; public static void Main (string [] args) {Console.WriteLine ("number of juster books:" + bookNum); Thread juster = new Thread (() = > {Console.WriteLine ("juster does not have books, waiting for parents to deliver books to school.") While (bookNum = = 0) {} Console.WriteLine ("juster gets the book and starts class.") ;}); juster.Name = nameof (juster); juster.Start (); Thread parent = new Thread () = > {Console.WriteLine ("parent is looking for a book in the house."); Thread.Sleep (2000); Console.WriteLine ("after parent finds the book, send it to school.") SendBook (); parent.Name = nameof (parent); parent.Start ();} public static void SendBook () {bookNum = 1;}}

After various optimizations, booknum is copied and modified in static methods because it is a value type that is accessed by each thread. So each thread copies the value of booknum into the current thread context and caches it. This causes the parent thread to modify the value of booknum that the juster thread cannot see. At this point, you need to use the volatile keyword to tell the compiler that no such optimization is needed, indicating that the variable defined in volatile will be changed and must be read from memory every time, instead of being reused in CPU cache or registers. Finally, the booknum will modify the value while running and other threads can "share access" to achieve the final effect.

3.Conclusion

Part1

The volatile keyword can be applied to the following types of fields:

Reference type.

Pointer type (in an unsafe context). Note that although the pointer itself can be mutable, the object it points to cannot be mutable. In other words, a pointer to a mutable object cannot be declared.

Simple types such as sbyte, byte, short, ushort, int, uint, char, float, and bool.

An enum type with one of the following basic types: byte, sbyte, short, ushort, int, or uint.

Generic type parameters that are known to be reference types.

IntPtr and UIntPtr.

Other types, including double and long, cannot be marked as volatile because reading and writing to these types of fields is not guaranteed to be atomic. To protect multithreaded access to these types of fields, use Interlocked class members or use lock statements to protect access.

The volatile keyword can only be applied to fields of class or struct. Local variables cannot be declared as volatile.

Part2

Volatile cannot be used for thread synchronization, its main purpose is to allow multiple threads to see the latest values after modification.

Part3

C # does not support passing volatile fields to methods by passing references.

Int.TryParse ("123", out x)

Part4

In addition to disabling compilation optimization, there is also synchronization to memory because each core of CPU has its own Cache, so it needs to be synchronized to memory for other cores to use.

Part5

After reading this article, I can also solve the wonder of the rookie period, why I can't run the error report after I wrote the code and compiled it to release.

Part6

The relevant knowledge and principles involved in volatile are far more than these.

This is the end of the content of "how to use Volatile in C#". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report