使用多个方法进行线程同步

3
我有一个包含多个静态方法的静态类。
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都是完全线程安全的,它们可以在任意数量的线程中同时被安全地调用。实际上,出于性能原因,我需要允许多个线程并发调用这三个方法。

问题在于,当调用Method4()时,Method1、Method2和Method3有可能抛出异常。 那么,在调用Method4()时如何允许多个线程调用Method1、Method2和Method3,同时也阻止它们调用这三个方法呢?


6
听起来你需要一个ReaderWriterLock。 - SLaks
你为什么要将会话设置为null?直接将会话设置为新的会话不就可以了吗? - Servy
Servy - 我可能过于简化了我的示例,但是Method4()基本上是:session.Disconnect()和session.Connect(newConfig)。在此过程中,我不希望Method1、2、3调用Action()。 - Pierre-Luc
我个人更喜欢使用 Rx.Net 的 RefCountDisposable。 - Aron
3个回答

4
正如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();
    }
}

性能优异,没有线程问题!


0
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()
}

-2

ManualResetEvent怎么样?

M4()
{
  _event.Reset();
  try
    //reconnect
  finally
    _event.Set();
}

M1,2,3()
{
  _event.WaitOne();
  //do actions
}

假设 M4 在1小时内没有被调用。 - L.B
@L.B,_event可以从已发信号状态开始。 - treehouse
那么对于M1、M2、M3的第二次调用呢?顺序是:M1(), M2(), - L.B
@L.B,我不确定我是否理解了你的关注点。对于ManualResetEvent,如果事件被标记为已发生且未重置,则WaitOne将立即返回。 - treehouse
1
抱歉,我无法解决我们之间的通信错误。算了吧。试着理解为什么这段代码不起作用。或者更好的办法是编写真正的代码并调用 M1(),M1(),M1() - L.B
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接