This blog will conduct a real machine test on the following four situations:
● Int cant in the class
● Volatile variable int CNT in the class
● Nonatomic attribute int CNT in the class
● Class atomic attribute int CNT
For more information about volatile keywords, see volatile keywords in C. Volatile tells the compiler that the memory value is forcibly used each time the variable I is calculated, rather than the value in the register.
Atomic, Operation atomicity, atomic or default value in the attribute declaration keyword.Note:It does not have the concept of "locking" memory, but the concept of "locking" a register (here it is actually a deadlock prevention mechanism that prevents others from continuing to access the value being modified, make sure that the data calculated in the register is used each time, instead of the data that is no longer used in the memory.
Nonatomic: gets the value directly from the memory, and does not have a lock protection to calculate the value in the CPU register. It is simply from the memory address, the data results stored in the current memory are used. Therefore, in multithreading, we should declare such variables nonatomic, because it can always respond to the getter method, to prevent you from getting half of the data, and the result data is released, or data is being written in other threads. This avoids the fact that the obtained data is not the one you expected (although this is not the data being modified by another thread ).
The tested data is as follows:
The core function in the demo is to perform operations on the CNT variable ++. 1000000 executions (you can set the number of cycles by yourself)
Click to download
It is learned that the lower the average time consumption, the longer the time consumption. Normal is the shortest, and atomic is the longest. Normal <volatile <nonatomic <atomic
● Under normal circumstances, the value of the variable CNT is cached in the register, but volatile forces the value calculation from the memory every time. The memory is slower than the register, and the result is that volatile is slower than normal.
● The reason nonatomic is faster than atomic is that it directly accesses the memory address, does not care "whether other threads change this value", and there is no deadlock protection in the middle, it only needs to directly access the data available in the current memory address from the memory (it can be understood that the getter method can always return a value, although the discount value may be being modified in the CPU ).
Atomic is thread insecure. Some people mistakenly believe that it is safe to add the atomic keyword to multiple threads.
Atomic modified variable CNT,It is only an atomic operation for getter and setter.If you perform ++ operations on CNT, it is not in the scope of atomic management.
For example, the following code:
@property int cnt; @synthesize cnt = _cnt; self.cnt = 0; for(i = 0 ; i < n ; i++) { self.cnt ++; }
After compilation, see the following assembly code:
L: movl CNT (% rip), % eax// Move the CNT value to the memory (load)
U: incl % eax// ++ Operation (updte)
S: movl % ECx, CNT (% rip)// Save the CNT value to the memory)
If both threads are running this code, CNT is a shared variable (the stacks run by different threads are different ). The three lines of assembly code are critical, that is, they cannot be interrupted. Otherwise, data errors may occur.
Case1: L1-> U1-> S1-> L2-> u2-> S2 translate into text: thread 1 loads CNT = 0 to the register, register ++ then saves the register value 1 to CNT. Thread 2 is going through this process, and finally CNT = 2. This order is okay. It can ensure that the CNT value can be ++ twice.
Case2: L1-> U1-> L2-> S1-> u2-> S2 translate into text: thread 1 loads CNT = 0 to the register, then the register ++ operation of thread 1 is performed. Thread 2 loads CNT = 0 to the register. Thread 1 saves register value 1 to CNT, registers ++ in thread 2, and thread 2 saves the register value (still 1) to CNT. The result is incorrect.
I personally think that the jurisdiction of the keyword atomic is not coveredL, U, SThese three assembly operations, so atomic is thread unsafe. Nonatomic is also thread unsafe. Only locking is required for thread security.
* ** In the middle of the cited netizens blog http://blog.csdn.net/a21064346/article/details/8086701 is hereby explained ***
*** Niu X's article http://archive.atomicmpc.com.au/forums.asp? S = 2 & C = 10 & t = 4594 ***