在我的多线程ASMX web服务,我有我自己的类型SystemData的类别字段_allData它由数List<T>和Dictionary<T>标记为volatile.系统data(_allData)会偶尔刷新一次,我会通过创建另一个被调用的对象newData并用新数据填充它的数据结构来实现.当它完成后我就分配了
private static volatile SystemData _allData
public static bool LoadAllSystemData()
{
SystemData newData = new SystemData();
/* fill newData with up-to-date data*/
...
_allData = newData.
}
Run Code Online (Sandbox Code Playgroud)
这应该工作,因为赋值是原子的,并且具有对旧数据的引用的线程继续使用它,而其余的在分配之后具有新的系统数据.然而,我的同事说,volatile我应该使用,而不是使用关键字和简单的InterLocked.Exchange分配,因为他说在某些平台上,不能保证引用赋值是原子的.另外:当我宣布the _allData字段volatile的
Interlocked.Exchange<SystemData>(ref _allData, newData);
Run Code Online (Sandbox Code Playgroud)
产生警告"对易变场的引用不会被视为不稳定的"我应该怎么看待这个?
我在类中有属性定义,我只有计数器,这必须是线程安全的,这不是因为get并且set不在同一个锁中,如何做到这一点?
private int _DoneCounter;
public int DoneCounter
{
get
{
return _DoneCounter;
}
set
{
lock (sync)
{
_DoneCounter = value;
}
}
}
Run Code Online (Sandbox Code Playgroud) 由于DateTime不能声明为volatile,这是对的吗?:
private DateTime _time;
public DateTime Time
{
get
{
Thread.MemoryBarrier();
return _time;
}
set
{
_time = value;
Thread.MemoryBarrier();
}
}
Run Code Online (Sandbox Code Playgroud)
该属性可以从不同的线程访问,所以我想确保它们始终获得最新版本,而不使用争用(锁定).
编辑:
我想确保当"删除线程"进入集合时,所有项目都有最新的"最后访问"DateTime,因此我可以避免再次创建项目,因为缓存保持该值几毫秒:d
提前致谢.
我正在阅读Joe的Albahari C#线程教程:
作者解释了为什么DateTime.Now需要线程安全:
只有当所有并发线程都知道并使用锁定时,才能对自定义锁定周围的对象进行包装访问.如果对象的范围很广,则可能不是这种情况.最糟糕的情况是公共类型的静态成员.例如,假设DateTime结构上的静态属性DateTime.Now不是线程安全的,并且两个并发调用可能导致输出乱码或异常.使用外部锁定解决此问题的唯一方法可能是在调用DateTime.Now之前锁定类型本身 - lock(typeof(DateTime)).只有当所有程序员都同意这样做时(这是不可能的),这才有效.此外,锁定类型会产生其自身的问题.
因此,DateTime结构上的静态成员已经过仔细编程,以确保线程安全.
根据MS docs,.NOW是public static DateTime Now { get; },即只读属性.如果它是只读的,为什么要打扰线程安全呢?两个并发呼叫应该能够获得当前时间而不会相互干扰?
编辑:很多人指出问题不是很清楚.我确实假设它应该是安全的,因为:它是只读的,因为它是时间(总是在改变).
我有多个线程使用"++"或" - "操作访问单个Int32变量.
我们是否需要在访问之前锁定,如下所示?
lock (idleAgentsLock)
{
idleAgents--; //we should place it here.
}
Run Code Online (Sandbox Code Playgroud)
或者如果我不进行锁定会有什么后果?
C#确保某些类型始终具有原子读取和写入.在调用Array.Copy这两种类型的数组时,我是否有同样的保证?每个元素是否以原子方式读写?我浏览了一些源代码,但没有得到一个可靠的答案.
例如,如果我推出自己的代码来复制两个数组......
static void Copy<T>(T[] source, T[] destination, int length)
{
for (int i = 0; i < length; ++i)
destination[i] = source[i];
}
Run Code Online (Sandbox Code Playgroud)
...并且调用了Copy<int>变体,这保证了每个元素都是从原子上读取source并原子写入的,destination因为C#承诺int读取和写入都是原子的.我只是问是否Array.Copy保持这种保证(相反,使用它自己的专用内存块复制例程,可能会破坏这种保证).
我可以想到一些使用案例,让DateTime对象成为原子非常有用.从语言设计的角度来看,有什么优势可以使DateTime不稳定?
我正在读一个Guid对象两次,一次是在if语句中,一次是在if语句的块中.
在CI中,将在本地复制变量,以确保if语句中的读取操作不会读取不同的值(如果另一个线程在中间更改此值).
我怀疑以下方法是a)线程安全和b)会给我相同的值:
public class MyClass {
private Guid MyProp {get;set;} = Guid.Empty; //May be changed at will
public OnRunLoop() //Gets called periodicaly on a thread
{
var ALocalCopyOfTheProp = MyProp; //Copy locally
if(ALocalCopyOfTheProp == AValueFromAnotherPlace) //Read 1
{
...
var AnotherReadOfTheVariable = ALocalCopyOfTheProp; //Read 2
}
...
}
Run Code Online (Sandbox Code Playgroud)
C#.NET本身没有谷歌搜索的复制功能,所以在这种情况下最佳做法是什么?
编辑: - 请注意,在这种情况下,MyProp不在我的手中.我不能使用锁,因为该物业来自其他地方.(道歉没有让它更清晰) - Guid是一个结构而不是引用类型