【问题标题】:Using Thread.VolatileWrite() with array parameters使用带有数组参数的 Thread.VolatileWrite()
【发布时间】:2009-01-17 12:19:15
【问题描述】:

我想使用Thread.VolatileWrite()(或等效函数)更改T[] 字段的值,以便所有其他线程立即看到更新后的值。但是,该方法不提供通用版本,并且我无法使用 Object 重载,因为它需要 ref 参数。

还有其他选择吗? Interlocked.Exchange<T> 会做这项工作吗?有没有更好的方法来实现我想做的事情?

【问题讨论】:

    标签: .net multithreading


    【解决方案1】:

    VolatileWrite 仅在您还使用VolatileRead 时才有用; volatile 修饰符更易于使用,但我想知道使用同步是否会更简单 - 也许是 ReaderWriterLockSlim (因为听起来你有很多读者)。

    Interlocked.Exchange<T> 只是简单地执行 get 和 set 作为原子操作;它(AFAIK)没有做出任何波动性声明(实际上,编译器甚至告诉您 volatile 字段在用作 ref 参数时不会被视为 volatile)。


    编辑以澄清“它(AFAIK)没有做出任何波动性声明” - Interlocked 的行为是可以预测的,您应该立即在其他线程上看到更新只要他们也使用Interlocked;我的观点是,如果一个线程使用Interlocked,而另一个线程依赖volatile(与同一个字段交谈),我不知道有任何保证。对于所有访问,请坚持使用其中一个。

    【讨论】:

    • 所以你的意思是,除非我也使用VolatileRead,否则其他线程可能仍然有该字段的缓存值?
    • 没错。因此,volatile 修饰符使这更简单。
    • 我试图使用它来支持使用 volatile 字段,因为该字段被非常频繁地访问,但只写入非常非常少的时间(例如,访问 3n 次,而写入 log(n ) 次)。所以我想我只能在写的情况下引入 VolatileWrite...
    • @Hosam:问题在于,除非阅读线程知道确保他们没有获得缓存版本,否则他们不能同时查看新发布的版本。事实上,我相信 .NET(即 MS CLI 实现)无论如何都会使所有写入变得易变——读取需要格外小心。
    【解决方案2】:

    您也许可以使用volatile 修饰符。但请查看文档以了解该限制不适用于您的案例。使用它可能会降低性能。

    更新:关于使用 Interlocked。请注意,文档没有说明更改的值对所有线程都是可见的。所以可能不太一样。但是,如果您处于这种情况,这很重要。您必须进一步调查所有并发灾难的可能性。

    【讨论】:

    • 谢谢。我已经在使用 volatile 修饰符,我希望可以通过显式调用 VolatileWrite 来避免它的惩罚。 (请参阅我对 Marc 回答的评论。)谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 2020-07-25
    • 2016-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多