【问题标题】:Thread synchronization with multiple methods多方法线程同步
【发布时间】:2014-02-04 19:31:34
【问题描述】:

我有一个包含多个静态方法的静态类。

private static Session _session = new Session();

public static void Method1() {
    if(_session != null)
        _session.Action();
}
public static void Method2() {
    if(_session != null)
        _session.Action();
}
public static void Method3() {
    if(_session != null)
        _session.Action();
}
public static void Method4(string path) {
    _session.Disconnect();
    _session.Connect(new Config(path));
}

Method1、Method2、Method3 是完全线程安全的,可以从任意数量的线程安全地同时调用它们。其实出于性能考虑,我需要允许多个线程同时调用Method1,2,3。

问题是,Method1,2,3 有可能在 Method4() 被调用时抛出异常。 如何在调用 Method4() 时允许多个线程调用 Method1,2,3 同时阻塞它们?

【问题讨论】:

  • 听起来你需要一个 ReaderWriterLock。
  • 为什么将会话设置为空?为什么不直接将会话设置为新会话?
  • Servy - 我可能过于简化了我的示例,但 Method4() 基本上是:session.Disconnect() 和 session.Connect(newConfig)。虽然发生这种情况,但我不希望 Method1、2、3 调用 Action()。
  • 我个人更喜欢使用 Rx.Net 的 RefCountDisposible。

标签: c# multithreading


【解决方案1】:

正如 SLaks 所指出的,ReadWriterLock 是一个很好的解决方案。

这是我最终实现的:

private static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private static Session _session = new Session();

public static void Method1() {
    _lock.EnterReadLock();
    try {
        if(_session != null)
            _session.Action();
    }
    finally
    {
        _lock.ExitReadLock();
    }
}
public static void Method2() {
    _lock.EnterReadLock();
    try {
        if(_session != null)
            _session.Action();
    }
    finally
    {
        _lock.ExitReadLock();
    }
}
public static void Method3() {
    _lock.EnterReadLock();
    try {
        if(_session != null)
            _session.Action();
    }
    finally
    {
        _lock.ExitReadLock();
    }
}
public static void Method4(string path) {
    _lock.EnterWriteLock();
    try {
        if(_session != null)
            _session.Action();
    }
    finally
    {
        _lock.ExitWriteLock();
    }
}

出色的性能,没有线程问题!

【讨论】:

    【解决方案2】:
    private static RefCountDisposable _refCountDisposible = new RefCountDisposable();
    private static Session _session = new Session();
    
    public Constructor()
    {
        _refCountDisposible = new RefCountDisposable(
               Disposible.Create(() => _session.Disconnect()));
    }
    
    public static void Method1() {
        using(_refCountDisposible.GetDisposible())
            if(_session != null)
                _session.Action();
    
    }
    public static void Method2() {
        using(_refCountDisposible.GetDisposible())
    
            if(_session != null)
                _session.Action();
    }
    public static void Method3() {
        using(_refCountDisposible.GetDisposible())
            if(_session != null)
                _session.Action();
    }
    public static void Method4(string path) {
        _refCountDisposible.Dispose()
    }
    

    【讨论】:

      【解决方案3】:

      ManualResetEvent 怎么样?

      M4()
      {
        _event.Reset();
        try
          //reconnect
        finally
          _event.Set();
      }
      
      M1,2,3()
      {
        _event.WaitOne();
        //do actions
      }
      

      【讨论】:

      • 假设 1 小时内没有调用 M4。
      • @L.B,_event 可以从信号状态开始。
      • 那么第二次调用M1,2,3呢。 Sequence: M1(), M2(),
      • @L.B,我不确定我是否理解您的担忧。对于 ManualResetEvent,如果未重置事件,WaitOne 将立即返回。
      • 对不起,我无法解决我们之间的通讯错误。忘了它。试着理解为什么这段代码不起作用。或者更好地编写一个真实的代码并调用M1(), M1(), M1()
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-12
      • 2012-11-15
      • 1970-01-01
      • 2021-10-25
      • 1970-01-01
      相关资源
      最近更新 更多