
This article mainly explains Three ways to realize spin lock based on Net Thread
Purchase discount m.fenfaw cn
Based on thread Spinwait realizes spin lock
Implementation principle: Based on Test--And--Set atomic operation
Use a data to indicate whether the current lock has been acquired. 0 means it has not been claimed. 1 means it has been acquired. When the lock is acquired, the_ Set the value of lock to 1, and then check whether the value before modification is equal to 0,
advantage:
- Do not use thread Spinwait method, the retry method will be empty, and the CPU will use its maximum performance to continuously assign and compare instructions, which will waste a lot of performance, thread Spinwait indicates that the CPU is currently in the spin lock cycle and can rest for several time cycles
- Problems needing attention when using spin lock: the code protected by spin lock should be executed in a very short time. If the time is too long, other threads will try again and again, which will affect the execution of other threads
Disadvantages:
- The current implementation does not consider fairness. If multiple threads fail to acquire locks at the same time, the thread that acquires the lock first in chronological order may not be the first to obtain success after releasing the lock,
Code implementation:
public static class ThreadSpinWaitDemo { private static int _lock = 0; private static int _counterA = 0; private static int _counterB = 0; public static void IncrementCounters() { while (Interlocked.Exchange(ref _lock, 1) != 0) { Thread.SpinWait(1); } ++_counterA; ++_counterB; Interlocked.Exchange(ref _lock, 0); } public static void GetCounters(out int counterA, out int counterB) { while (Interlocked.Exchange(ref _lock, 1) != 0) { Thread.SpinWait(1); } counterA = _counterA; counterB = _counterB; Interlocked.Exchange(ref _lock, 0); } }
Spin lock based on SpinWaite
The attribute is the number of SpinOnce methods. If it is within a certain number of times and the current logical core is greater than 1, thread will be called Spinwait function; If it exceeds a certain number of times or the number of logical cores in the current environment is equal to 1, it is used alternately
Thread.Sleep(0) and thread The yield function means to switch to other threads. If it exceeds a certain number of times, the current thread will sleep
SpinWaite solves thread Two problems in spinwait
- If the spin lock runs for too long, SpinWaite can prompt the operating system to switch to other threads or put the current thread into sleep,
- If the current environment has only one core logic, SpinWaite will not execute thread The spinwait function directly prompts the operating system to switch to other threads,
public static class ThreadSpinOnceDemo { private static int _lock = 0; private static int _counterA = 0; private static int _counterB = 0; public static void IncrementCounters() { var spinWait = new SpinWait(); while (Interlocked.Exchange(ref _lock, 1) != 0) { spinWait.SpinOnce(); } ++_counterA; ++_counterB; Interlocked.Exchange(ref _lock, 0); } public static void GetCounters(out int counterA, out int counterB) { var spinWait = new SpinWait(); while (Interlocked.Exchange(ref _lock, 1) != 0) { spinWait.SpinOnce(); } counterA = _counterA; counterB = _counterB; Interlocked.Exchange(ref _lock, 0); } }
Spin lock based on SpinLock
Encapsulates the logic of SpinWaite
SpinLock code implementation
public class ThreadSpinLockDemo { private static SpinLock _spinLock = new SpinLock(); private static int _counterA = 0; private static int _counterB = 0; public static void IncrementCounters() { bool lockTaken = false; try { _spinLock.Enter(ref lockTaken); ++_counterA; ++_counterB; } finally { if (lockTaken) { _spinLock.Exit(); } } } public static void GetCounters(out int counterA, out int counterB) { bool lockTaken = false; try { _spinLock.Enter(ref lockTaken); counterA = _counterA; counterB = _counterB; } finally { if (lockTaken) { _spinLock.Exit(); } } } }
Briefly describe thread Sleep (0) and thread The difference between yield
- In Windows system, thread Sleep calls the SleepEx function provided by the system, thread The yield function calls the SwitchToThread method provided by the system,
- The difference is that the SwitchToThread function will only switch to the thread of the queue to be run associated with the current core logic, not to the thread associated with other core logic, while the SleepEx function will switch to the thread in the queue to be run associated with any logical core, And make the current thread unable to re-enter the waiting queue within the specified time (if the thread is 0, the thread can re-enter the waiting queue immediately)
- Thread. In Linux and OSX Sleep function will call pthread provided by pthread class library when sleep time is not 0_ cond_ The timedwait function will call sched when the sleep time is 0_ Yield function, thread Yield will also call sched_yield function sched_yield is no different between windows and OSX systems. It will only switch to the threads in the queue to be run concerned by the current and logical core, and will not switch to the threads associated with other core logic. Calling the sleep function provided by the system on unix system and passing 0 will directly ignore the return
This paper is based on Net Core bottom entry summary
If there is anything that is not very clear or wrong, please correct it
If you like, you might as well like it 🙂
Personal wechat