相关疑难解决方法(0)

如何正确读取Interlocked.Increment'ed int字段?

假设我有一个非易失性的int字段,以及一个它Interlocked.Increment的线程.另一个线程可以直接安全地读取它,还是读取也需要互锁?

我以前认为我必须使用互锁读取来保证我看到当前值,因为毕竟,该字段不是易失性的.我一直在Interlocked.CompareExchange(int, 0, 0)努力实现这一目标.

但是,我偶然发现了这个答案,这表明实际的普通读取总会看到Interlocked.Incremented值的当前版本,并且因为int读取已经是原子的,所以不需要做任何特殊的事情.我还发现了Microsoft拒绝Interlocked.Read(ref int)请求的请求,进一步表明这完全是多余的.

那么我能真正安全地阅读这样一个int领域的最新价值Interlocked吗?

.net c# multithreading thread-safety

56
推荐指数
4
解决办法
1万
查看次数

"对易变场的引用不会被视为不稳定的"含义

以下代码

using System.Threading;

class Test
{
    volatile int counter = 0;
    public void Increment()
    {
        Interlocked.Increment(ref counter);
    }
}
Run Code Online (Sandbox Code Playgroud)

引发以下编译器警告:

"A reference to a volatile field will not be treated as volatile"
Run Code Online (Sandbox Code Playgroud)

我在这里做错了什么来提出这个警告?为什么编译器会对此发出警告?

.net c# multithreading volatile

42
推荐指数
3
解决办法
8607
查看次数

读取由Interlocked在其他线程上更新的int

(这是重复:如何正确读取Interlocked.Increment'ed int字段?但是,在阅读了答案和评论之后,我仍然不确定正确的答案.)

有些代码我不拥有,也无法更改为使用在几个不同线程中增加int计数器(numberOfUpdates)的锁.所有通话都使用:

Interlocked.Increment(ref numberOfUpdates);
Run Code Online (Sandbox Code Playgroud)

我想在我的代码中读取numberOfUpdates.既然这是一个int,我知道它不会撕裂.但是,确保我获得最新价值的最佳方法是什么?看起来我的选择是:

int localNumberOfUpdates = Interlocked.CompareExchange(ref numberOfUpdates, 0, 0);
Run Code Online (Sandbox Code Playgroud)

要么

int localNumberOfUpdates = Thread.VolatileRead(numberOfUpdates);
Run Code Online (Sandbox Code Playgroud)

两者都有效(无论优化,重新排序,缓存等,都可以提供最新的价值)?一个比另一个更受欢迎吗?还有第三种选择更好吗?

.net c# multithreading interlocked interlocked-increment

35
推荐指数
3
解决办法
1万
查看次数

Interlocked.CompareExchange是否使用内存屏障?

我正在阅读Joe Duffy关于Volatile读取和写入以及及时性的帖子,我正在尝试理解帖子中最后一个代码示例:

while (Interlocked.CompareExchange(ref m_state, 1, 0) != 0) ;
m_state = 0;
while (Interlocked.CompareExchange(ref m_state, 1, 0) != 0) ;
m_state = 0;
… 
Run Code Online (Sandbox Code Playgroud)

当执行第二CMPXCHG操作,它使用一个内存屏障,以保证价值m_state确实写入的最新值?或者它只是使用已存储在处理器缓存中的某些值?(假设m_state未声明为volatile).
如果我理解正确,如果CMPXCHG不会使用内存屏障,那么整个锁获取过程将不公平,因为第一个获取锁的线程很可能是将获得所有锁的线程.以下锁.我是否理解正确,或者我错过了什么?

编辑:主要问题实际上,在尝试读取m_state的值之前,调用CompareExchange是否会导致内存屏障.因此,当尝试再次调用CompareExchange时,是否所有线程都可以看到赋值0.

c# optimization multithreading volatile memory-model

18
推荐指数
3
解决办法
7122
查看次数