On most computers, adding a variable is not an atomic operation. You need to perform the following steps:
1.Load the values in instance variables into registers.
2.Increase or decrease the value.
3.Store this value in instance variables.
In a multi-threaded environment, the thread will be preemptible after the first two steps are executed. Then, the other thread executes all three steps,When the first thread starts execution again, it overwrites the value in the instance variable, resulting in loss of the result of the increase or decrease operation in the second thread.
InterlockedAtomic operations can be performed on variables shared by multiple threads.
- Interlocked. Increment:Increment the value of a specified variable in the form of an atomic operation and store the result.
- Interlocked. DecrementDecrease the value of the specified variable in the form of an atomic operation and store the result.
- Interlocked. AddIn the form of an atomic operation, add two integers and replace the first integer with the sum of the two.
HoweverInterlockedDivision does not provide atomic operations for multiplication. So how can we implement multiplication, division, and support other non-atomic operations ??
The key lies inInterlocked. compareexchangeJeffrey Richter calls it interlocked anything mode.
Below we useInterlocked. compareexchangeThe atomic operation that calculates the maximum value.
Public Static Int Maximum ( Ref Int Target, Int Value)
{
Int Currentval = Target; // Save the current value of target to currentval.
Int Startval, desiredval; // Declare two variables to record the value before the operation starts and the expected result value.
Do
{
Startval = Currentval; // Save the value in currentval to startval, and record the initial value of target before the operation starts.
Desiredval = Math. Max (startval, value ); // Perform complex calculation using startval and return an expected result. Here, only the maximum values of the two are returned.
// the thread may be preemptible here, the target value may be changed
// If the target value is changed, the values of target and startval do not need to be equal. Therefore, desiredval should not be used to replace target.
// If the target value is not changed, the values of target and startval are like the same. Use desiredval to replace target.
/// whether replaced or not, the return value of compareexchange is always the target value, so the value of currentval is now the latest value of target.
// Compareexchange: Compare the values of target and startval. If they are equal, replace them with desiredval. Otherwise, the operation is not performed,
// Whether it is replaced or not, the returned value is the value originally saved in the target.
Currentval = Interlocked. compareexchange ( Ref Target, desiredval, startval );
} While (Startval ! = Currentval ); // When the starting value of the target is not the same as the latest value, it indicates that the target has been modified, so proceed to the next judgment; otherwise, exit the loop.
Return Desiredval;
}
This sectionCodeThe core is: currentval=Interlocked. compareexchange (RefTarget, desiredval, startval );
// Compare the target value with the startval value. If the values are equal, replace the target with desiredval. Otherwise, the operation is not performed,
//Whether it is replaced or not, the returned value is the value originally saved in the target.
Here, the computation may be complicated, unlike the above math. Max, so you can use the delegate call Method for encapsulation.
Delegate Int Morpher < Tresult, targument > ( Int Startvalue, targument argument,
Out Tresult morphresult );
static tresult morph tresult, targument > ( ref int Target, targument argument,
morpher tresult, targument > morpher)
{< br> tresult morphresult;
IntCurrentval=Target, startval, desiredval;
Do
{
Startval = Currentval;
Desiredval = Morpher (startval, argument, Out Morphresult );
Currentval = Interlocked. compareexchange ( Ref Target, desiredval, startval );
} While (Startval ! = Currentval );
ReturnMorphresult;
}
The basic principle is the same as above.
References:
Http://www.albahari.com/threading/
CLR via C #3.0