【C# 线程】【同步锁一】SpinWait类 -同步基元|同步原语
2022/1/1 9:08:05
本文主要是介绍【C# 线程】【同步锁一】SpinWait类 -同步基元|同步原语,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Spinwait类
完成代码:SpinWait.cs (dot.net)
原理:
SpinOnce()执行一次,执行次数超过10之后,每次进行自旋便会触发Thread.Yield()上下文切换的操作,在这之后每5次会进行一次sleep(0)操作,每20次会进行一次sleep(1)操作。SpinOnce()执行一次是大概7个时钟周期。第一自旋例外,第一次的时候比较耗时。
SpinOnce(int32 num) 执行num次后进入sleep(1); SpinOnce执行一次是大概7个时钟周期。第一例外,第一次的时候比较耗时。
Thread.Sleep(0) 表示让优先级高的线程插队,如果没有线程优先级更高线程插队,那么就继续执行。
Thread.Yield() 让有需要的线程先执行,忽略线程优先级(低级别的线程也可以在core运行),而该线程进入就绪队列。
SpinWait 内部用的是Thread.SpinWait(),Thread.SpinWait()调用外部函数(private static extern void SpinWaitInternal(int iterations);)现实自旋。
属性
count 表示自旋次数
isNextSpinWillYield :自旋超过10次,开始yield模式
源代码:
public bool NextSpinWillYield { get { if (_count < 10) { return Environment.IsSingleProcessor; } return true; } }
方法
Reset();将count设置未0。
SpinOnce()执行一次,在次数超过10之后,每次进行便会触发Thread.Yield()上下文切换的操作,在这之后每5次会进行一次sleep(0)操作,每20次会进行一次sleep(1)操作。
SpinOnce(int32 num) 执行num次后进入sleep(1);SpinOnce方法都 thread.spin(nm).
核心代码
internal const int YieldThreshold = 10; // When to switch over to a true yield. private const int Sleep0EveryHowManyYields = 5; // After how many yields should we Sleep(0)? internal const int DefaultSleep1Threshold = 20; // After how many yields should we Sleep(1) frequently? private void SpinOnceCore(int sleep1Threshold) { if (( _count >= YieldThreshold && ((_count >= sleep1Threshold && sleep1Threshold >= 0) || (_count - YieldThreshold) % 2 == 0) ) || Environment.IsSingleProcessor) { if (_count >= sleep1Threshold && sleep1Threshold >= 0) { Thread.Sleep(1); } else { int yieldsSoFar = _count >= YieldThreshold ? (_count - YieldThreshold) / 2 : _count; if ((yieldsSoFar % Sleep0EveryHowManyYields) == (Sleep0EveryHowManyYields - 1)) { Thread.Sleep(0); } else { Thread.Yield(); } } } else { int n = Thread.OptimalMaxSpinWaitsPerSpinIteration; if (_count <= 30 && (1 << _count) < n) { n = 1 << _count; } Thread.SpinWait(n); } // Finally, increment our spin counter. _count = (_count == int.MaxValue ? YieldThreshold : _count + 1); }
使用案例:
using System.Diagnostics; using System.Reflection; class Program { static SpinLock sl = new(); static void Main(string[] args) { Stopwatch stopwatch = new (); SpinWait sw = new(); //每次自旋的时间 for (int i = 0; i <40; i++) { // sw.Reset();// SpinWait内部是 采用count 累计计数的,所以每次使用都要清零 stopwatch.Reset(); stopwatch.Start(); sw.SpinOnce(31); stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedTicks+sw.NextSpinWillYield.ToString()+"count:"+sw.Count); } } }
SpinOnce()执行一次是大概7个时钟周期。第一例外,第一次的时候比较耗时。
这篇关于【C# 线程】【同步锁一】SpinWait类 -同步基元|同步原语的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-03-01沐雪多租宝商城源码从.NetCore3.1升级到.Net6的步骤
- 2024-05-08首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!
- 2024-03-30C#设计模式之十六迭代器模式(Iterator Pattern)【行为型】
- 2024-03-29c# datetime tryparse
- 2024-02-21list find index c#
- 2024-01-24convert toint32 c#
- 2024-01-24Advanced .Net Debugging 1:你必须知道的调试工具
- 2024-01-24.NET集成IdGenerator生成分布式全局唯一ID
- 2024-01-23用CI/CD工具Vela部署Elasticsearch + C# 如何使用
- 2024-01-23.NET开源的简单、快速、强大的前后端分离后台权限管理系统