在 C# 中设置一个简单的 属性 有什么非线程安全的?
What is non threadsafe about a simple property get set in c#?
我已经阅读了大量关于如何使 属性 线程安全的讨论和示例。 this threadsafe wrapper class
页面上有一个
给出的例子是这样的:
internal class MyThreadSafeCass
{
// *** Lock ***
private object PropertyLock = new object();
// *** Property ***
private int m_Property = 0;
// *** Thread-safe access to Property using locking ***
internal int Property
{
get
{
lock (PropertyLock)
{
return m_Property;
}
}
set
{
lock (PropertyLock)
{
m_Property = value;
}
}
}
}
很清楚这里发生了什么,锁在做什么,但我很难理解为什么需要它。为什么以下 不是 线程安全的?会出什么问题?
internal class MyThreadSafeCass
{
// *** Property ***
private int m_Property = 0;
// *** Thread-safe access to Property using locking ***
internal int Property
{
get
{
return m_Property;
}
set
{
m_Property = value;
}
}
}
像这样的表达式:m_Property++;在多个线程中并行 returns 不同的值。特别是在多核上 cpus.
- 旧值被加载到 cpu 的缓存中。
- 该值将增加 cpu
- 新值将被保存回内存。
示例:
- 核心一将加载值为 10
- 核心二将与核心一同时加载值为10
- 都加一(值为11)
- 两者都会将数据保存回内存
- 结果将是 11。
- 但你期望 12
有关详细信息,请参阅 this
@Enigmativity 通过链接到 this blog about skipping locks, which in turn links to this blog about CPU reordering optimizations 获得荣誉(不幸的是,如果不是分数),这是答案的真正内容。
总而言之,CPU 可以(并且确实)对涉及更改 reads/writes 执行顺序的代码应用优化。这些更改保证在它们执行的线程内是一致的和不可察觉的。但是,它们不(不能)保证访问共享内存的多个线程之间的一致性。如初始问题中的示例所示,锁定对访问恢复一致性的共享内存施加了限制。
正如我所说,这是一个总结。我无法向上面链接的博客中的描述添加任何内容,因此请推迟任何有兴趣了解完整答案的人点击这些链接。
@Enigmativity,如果你这样 post 我仍然会接受你的回答。否则,我会接受这个答案并关闭它。
我已经阅读了大量关于如何使 属性 线程安全的讨论和示例。 this threadsafe wrapper class
页面上有一个给出的例子是这样的:
internal class MyThreadSafeCass
{
// *** Lock ***
private object PropertyLock = new object();
// *** Property ***
private int m_Property = 0;
// *** Thread-safe access to Property using locking ***
internal int Property
{
get
{
lock (PropertyLock)
{
return m_Property;
}
}
set
{
lock (PropertyLock)
{
m_Property = value;
}
}
}
}
很清楚这里发生了什么,锁在做什么,但我很难理解为什么需要它。为什么以下 不是 线程安全的?会出什么问题?
internal class MyThreadSafeCass
{
// *** Property ***
private int m_Property = 0;
// *** Thread-safe access to Property using locking ***
internal int Property
{
get
{
return m_Property;
}
set
{
m_Property = value;
}
}
}
像这样的表达式:m_Property++;在多个线程中并行 returns 不同的值。特别是在多核上 cpus.
- 旧值被加载到 cpu 的缓存中。
- 该值将增加 cpu
- 新值将被保存回内存。
示例:
- 核心一将加载值为 10
- 核心二将与核心一同时加载值为10
- 都加一(值为11)
- 两者都会将数据保存回内存
- 结果将是 11。
- 但你期望 12
有关详细信息,请参阅 this
@Enigmativity 通过链接到 this blog about skipping locks, which in turn links to this blog about CPU reordering optimizations 获得荣誉(不幸的是,如果不是分数),这是答案的真正内容。
总而言之,CPU 可以(并且确实)对涉及更改 reads/writes 执行顺序的代码应用优化。这些更改保证在它们执行的线程内是一致的和不可察觉的。但是,它们不(不能)保证访问共享内存的多个线程之间的一致性。如初始问题中的示例所示,锁定对访问恢复一致性的共享内存施加了限制。
正如我所说,这是一个总结。我无法向上面链接的博客中的描述添加任何内容,因此请推迟任何有兴趣了解完整答案的人点击这些链接。
@Enigmativity,如果你这样 post 我仍然会接受你的回答。否则,我会接受这个答案并关闭它。