用C#标签提出这个问题,但是如果可能的话,应该可以使用任何语言.
是否可以使用Interlocked操作实现双向链表以提供无等待锁定?我想插入,添加和删除,并清除,而不是等待.
两个Windows进程的内存映射了相同的共享文件.如果文件由计数器组成,是否适合使用Interlocked*函数(如InterlockedIncrement)来更新这些计数器?那些会跨进程同步访问吗?或者我需要使用更重的东西,比如互斥体?或者共享内存机制本身也可以确保一致的视图.
在SO上有很多关于Interlockedvs 的问题volatile,我理解并且知道volatile(没有重新排序,总是从内存中读取等)的概念,并且我知道它是如何Interlocked工作的,它执行原子操作.
但我的问题是:假设我有一个从多个线程中读取的字段,这是一些引用类型,例如:public Object MyObject;.我知道,如果我这样做就可以了比较交流,是这样的:Interlocked.CompareExchange(ref MyObject, newValue, oldValue)即互锁担保,只写newValue该存储位置ref MyObject指的是,如果ref MyObject和oldValue目前指的是同一个对象.
但阅读呢?并Interlocked保证任何线程读取MyObject后CompareExchange成功将立即获得新的价值经营,或者我必须标记MyObject为volatile保证呢?
我想知道的原因是我已经实现了一个无锁链接列表,当你为它添加一个元素时,它会不断地更新其内部的"head"节点,如下所示:
[System.Diagnostics.DebuggerDisplay("Length={Length}")]
public class LinkedList<T>
{
LList<T>.Cell head;
// ....
public void Prepend(T item)
{
LList<T>.Cell oldHead;
LList<T>.Cell newHead;
do
{
oldHead = head;
newHead = LList<T>.Cons(item, oldHead);
} while (!Object.ReferenceEquals(Interlocked.CompareExchange(ref head, newHead, oldHead), oldHead));
}
// ....
} …Run Code Online (Sandbox Code Playgroud) 我很困惑,微软表示InterlockedExchange需要内存对齐,但是,英特尔文档说LOCK不需要内存对齐.我错过了什么,或者其他什么?谢谢
Platform SDK:DLL,进程和线程InterlockedExchange
Target参数指向的变量必须在32位边界上对齐 ; 否则,此函数将在多处理器x86系统和任何非x86系统上出现不可预测的行为.
LOCK指令在执行伴随指令期间使处理器的LOCK#信号有效(将指令转换为原子指令).在多处理器环境中,LOCK#信号确保处理器在信号被置位时独占使用任何共享存储器.
LOCK前缀的完整性不受存储器字段对齐的影响. 对于任意未对齐的字段,观察到存储器锁定.
P6中的内存排序和更新的处理器系列
锁定的指令有一个总订单.
软件控制总线锁定
总线锁的完整性不受存储器字段对齐的影响.遵循LOCK语义以获得更新整个操作数所需的多个总线周期.但是,建议锁定访问在其自然边界上对齐,以获得更好的系统性能:•8位访问的任何边界(锁定或其他).•锁定字访问的16位边界.•锁定双字访问的32位边界.•锁定四字访问的64位边界.
我已阅读文章同步和多处理器问题,我有一个关于InterlockedCompareExchange和InterlockedExchange的问题.问题实际上是文章中的最后一个例子.它们有两个变量iValue,fValueHasBeenComputed并且在CacheComputedValue()它们中使用InterlockedExchange以下方法修改它们:
InterlockedExchange ((LONG*)&iValue, (LONG)ComputeValue()); // don't understand
InterlockedExchange ((LONG*)&fValueHasBeenComputed, TRUE); // understand
Run Code Online (Sandbox Code Playgroud)
我知道我可以InterlockedExchange用来修改,iValue但它应该只是做
iValue = ComputeValue();
Run Code Online (Sandbox Code Playgroud)
那么实际上是否需要使用InterlockedExchange来设置iValue?或者其他线程即使正确也会看到iValue iValue = ComputeValue();.我的意思是其他线程会正确地看到iValue,因为它InterlockedExchange在它之后.
还有针对Microsoft本机代码平台的基于原理的顺序内存模型.有3.1.1示例或多或少相同的代码.其中一个推荐Make y interlocked.请注意-不能同时y和x.
更新
只是为了澄清这个问题.问题是我看到了一个矛盾."同步和多处理器问题"中的示例使用两个InterlockedExchange.相反,在示例3.1.1"Basic Reodering"(我认为与第一个示例非常相似)中,Herb Sutter给出了这个推荐
"使y互锁:如果y是互锁的,那么y上没有竞赛,因为它是原子可更新的,并且x上没有竞赛,因为a - > b - > d."
.在这个草案草案中不要使用两个互锁变量(如果我是对的,他的意思是InterlockedExchange仅用于y).
有没有办法对存储在内存映射文件中的值使用Interlocked.CompareExchange();和Interlocked.Increment();方法?
我想实现一个多线程服务,将其数据存储在内存映射文件中,但由于它是多线程的,我需要防止冲突写入,因此我想知道Interlocked操作而不是使用显式锁.
我知道可以使用本机代码,但可以在.NET 4.0上的托管代码中完成吗?
我正在尝试编写一个只能调用一次的线程安全方法(每个对象实例).如果之前已调用异常,则应抛出异常.
我想出了两个解决方案.他们都是正确的吗?如果没有,他们有什么问题?
用lock:
public void Foo()
{
lock (fooLock)
{
if (fooCalled) throw new InvalidOperationException();
fooCalled = true;
}
…
}
private object fooLock = new object();
private bool fooCalled;
Run Code Online (Sandbox Code Playgroud)public void Foo()
{
if (Interlocked.CompareExchange(ref fooCalled, 1, 0) == 1)
throw new InvalidOperationException();
…
}
private int fooCalled;
Run Code Online (Sandbox Code Playgroud)
如果我没有弄错的话,这个解决方案具有无锁的优点(在我的情况下似乎无关紧要),并且它需要更少的私有字段.
我也愿意接受合理的意见,哪些解决方案应该是首选的,并且如果有更好的方法可以提出进一步的建议.
我已经包含了windows.h,并希望在vs2010中使用InterlockedAdd并编译错误"未找到标识符",但是InterlockedIncrement可以正常工作.我尝试使用:
#include <intrin.h>
#pragma intrinsic(_InterlockedAdd)
Run Code Online (Sandbox Code Playgroud)
并编译错误:
警告C4163:'_InterlockedAdd':不可用作内部函数
1> test10.cpp(107):错误C3861:'InterlockedAdd':未找到标识符
代码有什么问题?
我刚刚学会了互锁类,它应该比简单锁定更快.现在,这一切都很好,但我对实施感到好奇.
据我所知,确保变量操作是以原子方式完成的唯一方法是确保只有一个线程可以随时访问该变量.哪个是锁定的.
我用反射器来获取Interlocked的来源,但似乎它使用外部方法来完成它的所有工作:
[MethodImpl(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal static extern int ExchangeAdd(ref int location1, int value);
Run Code Online (Sandbox Code Playgroud)
我已经运行了一些测试,实际上Interlocked只是锁定对象并增加它的速度的两倍.
他们是怎么做到的?
我正在尝试在多线程.NET应用程序中的共享变量中设置位标志,但无法找到与托管的Interlocked类中的本机InterlockedOr函数的并行.我已经提出了以下用于执行| =赋值的代码,但无限循环的理论可能性让我感到不舒服:
long currentValue;
long updatedValue;
do
{
// Spin until successful update. Value must be read using Interlocked.Read()
// to be truly atomic on 32 bit systems (see MSDN).
currentFlags = Interlocked.Read(ref _currentFlags);
updatedValue = currentFlags | flag;
} while (currentFlags != Interlocked.CompareExchange(ref _currentFlags, updatedValue, currentFlags));
Run Code Online (Sandbox Code Playgroud)
是否可以仅使用Interlocked类中内置的函数以更安全的方式实现?如果可能的话,我想避免涉及显式锁定的解决方案.