【问题标题】:Make property thread safe in c# with a semaphore or lock?使用信号量或锁在 c# 中使属性线程安全?
【发布时间】:2014-01-25 10:54:56
【问题描述】:

我是响应式的新手,但这个想法激发了我的好奇心,所以我做了一些响应式变量,但我不知道这是否是最佳实践,然后我会将这个线程安全。

课程如下:

 public class RxVar<T>:IObservable<T>
 {

     T _value;
     public T Value
     {

         get{ 
             return _value;
         }
         set{
             if (!_value.Equals(value))
             {
                 onChange(_value);
                 _value = value;
             }
         }

     }


     event onValChange onChange = delegate { };
     delegate void onValChange(T val);

     IObservable<T> _observable;
     public RxVar() {

         _observable = Observable.FromEvent<onValChange,T>(ev => onChange += ev, ev => onChange -= ev);
     }

     public IDisposable Subscribe(IObserver<T> observer)
     {
         return _observable.Subscribe(p=>observer.OnNext(p));
     }
 }

信号量示例

         _semaphoreSlim.WaitOne();
         if (!_value.Equals(value))
         {
             onChange(_value);
             _value = value;
         }
         _semaphoreSlim.release();

好的,我想让这个线程安全,但我害怕死锁。所以, 最好使用lock 或信号量,或者由于反应性质,不需要它?

谢谢。 :)

【问题讨论】:

    标签: c# multithreading locking system.reactive semaphore


    【解决方案1】:

    我建议使用锁而不是信号量。在这种情况下,信号量只是错误的工具。

    考虑用“return _value”暴露实际值意味着即使在 getter 返回之后,客户端代码也能够修改对象中的数据。所以问题是在暴露了引用之后如何避免竞争条件?

    答案是不要暴露参考。提供对象/数据的深度副本,而不是原始对象本身。

    关于死锁:如果你知道自己在做什么,就不应该害怕。如果您不这样做,您将无法判断永远不会出现死锁,因为每次运行条件可能会有所不同,即使经过多次成功的测试,您也可能会导致死锁和调试,这将是一项艰巨的任务.

    只能通过事先研究来避免死锁,而不是通过任何“不知不觉编程”的方式。

    带锁的小sn-p:

    类实例字段(如果_value可以为null,则需要此字段,否则您可以锁定_value本身):

    private object _valueLock = new Int(0);
    

    在你的方法中:

    lock(_valueLock)
    {
        if (_value != value) // this or deep equality
        {
            _value = value;
            onChange(this, _value); // for complex Observer-Observable scenarios it's better specifying the observed object
        }
    }
    

    【讨论】:

    • 真的谢谢,反正我不明白为什么semaphone不能做这个工作:)
    • 信号量最适合其他场景,例如 producer/consumerreaders/writer。这个案例是一个简单的mutual exclusion,因此可能有更简洁的代码和更高效的实现。
    猜你喜欢
    • 2021-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多