SpinLock 真的不做忙循环等待吗?
SpinLock doesn't really do busy-loop waiting?
我有以下代码
class Program
{
static SpinLock sl = new SpinLock();
public static void Foo(object arg)
{
bool r = false;
sl.Enter(ref r);
}
public static void Main(string[] args)
{
bool r = false;
sl.Enter(ref r);
ThreadPool.QueueUserWorkItem(Foo);
Thread.Sleep(5000);
sl.Exit();
Thread.Sleep(5000);
}
}
当我执行它时,我发现整个程序 CPU 的负载约为 0% 运行。由于在 sl.Enter()
调用中旋转,我希望看到一些 CPU 燃烧,但事实并非如此。
根据 SpinLock source,它在幕后使用 SpinWait
,实际上在某些时候调用 Thread.Sleep(1)
。
这是否意味着 SpinLock
和 SpinWait
都不是真正的“旋转器”,而是仍然求助于 OS 调度程序来产生一些 CPU 份额?
编辑
问题可以通过以下方式重新表述:
使用忙循环确保一个线程释放锁和另一个线程获取锁之间的时间最短。在这方面我可以依靠 SpinLock
/SpinWait
吗?据我所知,答案是 否 ,因为它会 Sleep
至少 1 微秒,并且在此期间可能会在某处释放锁。
关于您编辑过的问题,是的,忙碌的旋转将使线程之间的通信延迟最低,但您将通过燃烧 CPU 时间来为此付出代价。
另一方面,您可以使用 SpinWait
,它不那么激进,或者您可以在两者之间编写代码,例如 this。
这归结为您对延迟的重视程度与您必须备用的内核数之间的权衡。
我有以下代码
class Program
{
static SpinLock sl = new SpinLock();
public static void Foo(object arg)
{
bool r = false;
sl.Enter(ref r);
}
public static void Main(string[] args)
{
bool r = false;
sl.Enter(ref r);
ThreadPool.QueueUserWorkItem(Foo);
Thread.Sleep(5000);
sl.Exit();
Thread.Sleep(5000);
}
}
当我执行它时,我发现整个程序 CPU 的负载约为 0% 运行。由于在 sl.Enter()
调用中旋转,我希望看到一些 CPU 燃烧,但事实并非如此。
根据 SpinLock source,它在幕后使用 SpinWait
,实际上在某些时候调用 Thread.Sleep(1)
。
这是否意味着 SpinLock
和 SpinWait
都不是真正的“旋转器”,而是仍然求助于 OS 调度程序来产生一些 CPU 份额?
编辑
问题可以通过以下方式重新表述:
使用忙循环确保一个线程释放锁和另一个线程获取锁之间的时间最短。在这方面我可以依靠 SpinLock
/SpinWait
吗?据我所知,答案是 否 ,因为它会 Sleep
至少 1 微秒,并且在此期间可能会在某处释放锁。
关于您编辑过的问题,是的,忙碌的旋转将使线程之间的通信延迟最低,但您将通过燃烧 CPU 时间来为此付出代价。
另一方面,您可以使用 SpinWait
,它不那么激进,或者您可以在两者之间编写代码,例如 this。
这归结为您对延迟的重视程度与您必须备用的内核数之间的权衡。