我有一个有几个属性的课程。在每次更新值时,都会调用Store
方法来存储所有字段(在文件中)。
private int _Prop1;
public int Prop1 {
get {
return _Prop1;
}
set {
_Prop1 = value;
Store();
}
}
// more similar properties here...
private XmlSerializer _Ser = new ...;
private void Store()
{
lock (_Ser) {
using (FileStream fs = new ...) {
_Ser.Serialize (fs, this);
}
}
}
这个设计是否是线程安全的?
(顺便说一句,如果您能想到更合适的标题,请随时编辑。)
我认为它是线程安全的。如果在多个线程上更改了属性,则值将按随机顺序设置,原子存储将以随机顺序发生,但最终,每个属性都将具有其最新值,并且最后会发生原子存储,确保文件是最新的。
澄清:不会经常设置属性,但可以同时设置它们。重要的是大部分时间都有一个有效的文件。
如果某个线程要根据属性值更改属性,则必须锁定整个对象以与其他线程同步。这与枚举List
上的锁定基本相同,并不是此类的责任。
答案 0 :(得分:5)
这取决于你在不同线程上调用的内容。
如果一次在不同的线程上设置属性,则它不是线程安全的,因为属性在序列化时可能会发生变化。
答案 1 :(得分:1)
没有
如果你想同步属性theirself,这段代码不是线程安全的,因为'lock'不在_Prop1值上,而只在_Ser上。实际上,当一个线程进入该属性时,该属性可以由另一个线程设置。
即使是序列化过程,_Ser访问可以被执行中的其他线程更改的属性(当_Ser正在运行时,另一个线程集Prop1)。
此代码实际上不允许多个线程使用XmlSerialize _Ser对象。如果它是您想要的...
答案主要取决于你想得到什么。
答案 2 :(得分:1)
没有足够的代码来拨打电话。但是可以肯定的是,如果您没有序列化对文件的写访问权,那么将不会发生任何好事。如果第一个线程仍在忙于写入文件,则分配属性的第二个线程将在IOException上进行炸弹。
像这样的细粒度锁定通常是个问题。客户端代码可能忙于更改类的多个属性。如果引发异常,您将获得部分更新,从而生成包含无效序列化状态的文件,并且在读取时可能会造成麻烦。你需要像BeginUpdate(),EndUpdate()对这样的东西。
答案 3 :(得分:0)
答案 4 :(得分:0)
如果可以从多个主题调用Prop1
属性,请创建_Prop1
字段volatile
。
private volatile int _Prop1;
来自MSDN,
volatile 关键字表示a 字段可能会被多个修改 正在执行的线程 时间。声明的字段 volatile 不受编译器限制 假设访问的优化 单线程。这确保了 最新的价值存在于 在任何时候都在这个领域。
考虑一下好的做法。它不会使您发布的代码线程安全,因为正如其他人所说,在序列化类时,_Prop1
的值可以被另一个线程更改。但是,如果您有一个能够由多个线程读取和写入的字段,则将该字段标记为volatile可确保您的代码看到最新值。
答案 5 :(得分:0)
不是线程安全的,除非属性类型是原子的。
简单的例子,带有线程A和B.
A: Prop1 = foo
A: Store()
A: ... store saves foo.Var1
B: Prop1 = bar
A: ... store saves bar.Var2 (instead of foo.Var2)
数据的完整性可能会受到影响。即使类型与Int64一样简单,理论上也可能出现问题。
在设置器中放置另一个lock(_Ser)
会有所帮助。