包含要在锁定操作中使用的对象的字典

时间:2018-11-19 20:29:03

标签: c# multithreading locking

如果我有一个需要从多个线程访问的非线程安全对象(例如NetworkStream),则可以安全地持有一个用于锁定的对象,以保护该非线程安全对象。一个ConcurrentDictionary(或常规Dictionary)的值中的安全对象?

即这样,我可以有多个线程,每个线程都试图将数据写入客户端的NetworkStream,但是每次都只允许一个线程吗?

我假设这是安全的,因为对象是引用类型,但希望有人能够确认。

使用ConcurrentDictionary的示例。 Send()方法将由多个线程调用。目的是允许多个调用者具有对NetworkStream的写访问权限,而我的好奇心是,在这种情况下,是否可以可靠地将ConcurrentDictionary值中找到的对象用于锁定。

// Assume this is prepopulated
private ConcurrentDictionary<string, object> locks = ...

public void Send(string identifier, byte[] data)
{
  object clientLock = null;
  if (locks.TryGetValue(identifier, out clientLock))
  {
    lock (clientLock)
    {
      // assume we have the TcpClient here
      NetworkStream ns = client.GetStream();
      ns.Write(data, 0, data.Length);
    }
  }
}

2 个答案:

答案 0 :(得分:-1)

在这种情况下,字典和互斥锁可能通常都不是必需的。通常,您使用私有对象互斥锁,以避免死锁。这样,其他任何代码都无法尝试对此进行锁定。但是在这种情况下,互斥对象及其所用的东西实际上都是 public

如果每个线程都能够在ClientStreams和互斥对象上运行锁定/解锁,则它们无法实现其目的。无论什么,您都可以锁定“ ClientStream”实例。

或者,使用类型为object和ClientStream的类,结构或tupel。这样,您至少可以将Mutex和hte ClientStream同时使用。

答案 1 :(得分:-1)

经过测试,即可正常运行。感谢大家的热烈交谈。当运行下面的示例代码时,Worker2将延迟。

    static ConcurrentDictionary<string, object> locks = new ConcurrentDictionary<string, object>();

    static void Main(string[] args)
    {
        locks.TryAdd("foo", new object());
        Task.Run(() => Worker1());
        Task.Run(() => Worker2());
        Console.ReadKey();
    } 

    static void Worker1()
    {
        object lockObj = null;
        locks.TryGetValue("foo", out lockObj);
        lock (lockObj)
        {
            Console.WriteLine("Worker1");
            Thread.Sleep(10000);
        }
    }

    static void Worker2()
    {
        object lockObj = null;
        locks.TryGetValue("foo", out lockObj);
        lock (lockObj)
        {
            Console.WriteLine("Worker2"); 
        }
    }