C# 使用记忆屏障
在下面的代码示例中,是否需要FuncA中的内存屏障来确保读取最新的值C# 使用记忆屏障,c#,multithreading,lock-free,memory-model,C#,Multithreading,Lock Free,Memory Model,在下面的代码示例中,是否需要FuncA中的内存屏障来确保读取最新的值 class Foo { DateTime m_bar; void FuncA() // invoked by thread X { Thread.MemoryBarrier(); // is required? Console.WriteLine(m_bar); } void FuncB() // invoked by thread Y { m_ba
class Foo
{
DateTime m_bar;
void FuncA() // invoked by thread X
{
Thread.MemoryBarrier(); // is required?
Console.WriteLine(m_bar);
}
void FuncB() // invoked by thread Y
{
m_bar = DateTime.Now;
}
}
编辑:如果不是,如何确保FuncA读取最新的值?我想确保最近的值实际上存储在处理器的缓存中[不使用锁]对我来说似乎是一个很大的否定。MemoryBarrier仅同步实现它的线程内的内存访问 从MSDN: 执行当前线程的处理器不能以这样的方式对指令重新排序:在调用MemoryBarrier之前的内存访问在调用MemoryBarrier之后的内存访问之后执行
对我来说,这是一个很大的拒绝。MemoryBarrier仅同步实现它的线程内的内存访问 从MSDN: 执行当前线程的处理器不能以这样的方式对指令重新排序:在调用MemoryBarrier之前的内存访问在调用MemoryBarrier之后的内存访问之后执行
我建议您将Datetime存储为ticks of ticks,它的类型为long,即Int64,您可以轻松地将ticks从new Datetime ticks转换为ticks myDateTime.ticks。然后,您可以在快速非锁定操作中使用Interlocked.Read-to-Read值和Interlocked.Exchange-to-write值 我建议您将Datetime存储为ticks of ticks,它的类型为long,即Int64,您可以轻松地将ticks从new Datetime ticks转换为ticks myDateTime.ticks。然后,您可以在快速非锁定操作中使用Interlocked.Read-to-Read值和Interlocked.Exchange-to-write值 是的,需要内存屏障,以便获得最新的值 如果内存屏障不存在,则线程X可以从其自己的缓存线读取m_bar的值,而该值尚未写回主存,更改已被设置为线程Y的本地。您可以通过将变量声明为volatile来实现相同的效果: volatile修饰符通常用于由多个线程访问而不使用lock语句序列化访问的字段。使用volatile修饰符可以确保一个线程检索另一个线程写入的最新值
关于这个问题的一个很好的条目可能最好是Joe Duffy的这一条:是的,需要内存屏障,以便您可以获得最新的值 如果内存屏障不存在,则线程X可以从其自己的缓存线读取m_bar的值,而该值尚未写回主存,更改已被设置为线程Y的本地。您可以通过将变量声明为volatile来实现相同的效果: volatile修饰符通常用于由多个线程访问而不使用lock语句序列化访问的字段。使用volatile修饰符可以确保一个线程检索另一个线程写入的最新值
关于这个问题的一个很好的条目可能是Joe Duffy的这一条最好的条目:内存屏障的作用与wat锁定的作用是一样的,保证字段将得到它的 进入锁时内存中的最新值,并在退出锁前写入内存。 确保字段的值始终读取或写入内存,并且从不通过读取或写入进行优化 也可以通过使用volatile关键字来实现对cpu缓存的第一次访问。 除非基元整数类型和引用类型不能缓存在CPU寄存器ad中,否则DateTime
不需要也不能用volatile关键字声明。内存屏障的作用与wat锁定的作用相同,保证字段将获得其 进入锁时内存中的最新值,并在退出锁前写入内存。 确保字段的值始终读取或写入内存,并且从不通过读取或写入进行优化 也可以通过使用volatile关键字来实现对cpu缓存的第一次访问。 除非基元整数类型和引用类型不能缓存在CPU寄存器ad中,否则DateTime
不需要也不能用volatile关键字声明。这实际上无关紧要,因为在32位体系结构上,在这种情况下可以得到一个撕裂的读取。这实际上无关紧要,因为在32位体系结构上,在这种情况下也可以得到撕裂的读取。。。。听起来像是家庭作业其实不是,只是出于兴趣。你为什么要把尸体移走?如果你不再喜欢你的问题,请删除它,不要让它成为一个无用的空问题。不要删除它,因为有太多的答案/投票。不要关闭它,它太脏了,无法删除正文的内容,让它成为一个空问题。这个问题有点相关和有趣,就让它原样吧。没有人投反对票,我发现这是一个有趣的问题。而且。。。听起来像是家庭作业,其实不是,只是出于兴趣。你为什么去掉b
奥迪?如果你不再喜欢你的问题,请删除它,不要让它成为一个无用的空问题。不要删除它,因为有太多的答案/投票。不要关闭它,它太脏了,无法删除正文的内容,让它成为一个空问题。这个问题有点相关和有趣,就让它原样吧。没有人投反对票,事实上我发现这是一个有趣的问题。这是不使用同步块监视器的唯一方法。进入和退出,也称为lockfoo,因为联锁仅适用于长或整数。这里的一个示例:这是不使用同步块监视器的唯一方法。进入和退出,也称为lockfoo,因为Interlocated只适用于long或int。这里有一个例子:有趣的是,MemoryBarrier的描述在.NET 2.0和.NET 3.5 2.0=>中有所不同。实际上,为执行当前线程的处理器将缓存内存的内容刷新到主内存。3.5==>按如下方式同步内存访问:执行当前线程的处理器不能以这样的方式重新排列指令,即调用MemoryBarrier之前的内存访问在调用MemoryBarrier之后的内存访问之后执行。有趣的是,MemoryBarrier的描述在.NET 2.0和.NET 3.5 2.0中有所不同=>同步内存。实际上,为执行当前线程的处理器将缓存内存的内容刷新到主内存。3.5==>按如下方式同步内存访问:执行当前线程的处理器不能以这样的方式重新排序指令:在调用MemoryBarrier之前的内存访问在调用MemoryBarrier之后的内存访问之后执行。