包含要在锁定操作中使用的对象的字典
Dictionary containing objects to be used in lock operations
在我有一个需要从多个线程访问的非线程安全对象(例如 NetworkStream)的情况下,持有一个用于锁定的对象是否安全,以保护非-线程安全对象,在 ConcurrentDictionary(或常规字典)的值中?
即这样,我可以有多个线程,每个线程都尝试将数据写入客户端的 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);
}
}
}
在这种情况下,Dictionary 和 mutex 通常可能是不必要的。通常你使用 private object mutex 来避免死锁。这样就没有其他代码可以尝试获取对此的锁定。但在这种情况下,互斥对象和它所用的东西实际上都是 public.
如果每个线程都能够在 ClientStreams 和互斥体对象上 运行 lock/unlock,则它们无法实现其目的。您可以锁定 "ClientStream" 实例,无论它是什么。
或者,使用类型对象和 ClientStream 创建一个 class、结构或元组。这样你至少可以同时拥有 Mutex 和 hte ClientStream。
刚刚测试,它按预期工作。感谢大家的热烈讨论。 运行下面的示例代码时,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");
}
}
在我有一个需要从多个线程访问的非线程安全对象(例如 NetworkStream)的情况下,持有一个用于锁定的对象是否安全,以保护非-线程安全对象,在 ConcurrentDictionary(或常规字典)的值中?
即这样,我可以有多个线程,每个线程都尝试将数据写入客户端的 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);
}
}
}
在这种情况下,Dictionary 和 mutex 通常可能是不必要的。通常你使用 private object mutex 来避免死锁。这样就没有其他代码可以尝试获取对此的锁定。但在这种情况下,互斥对象和它所用的东西实际上都是 public.
如果每个线程都能够在 ClientStreams 和互斥体对象上 运行 lock/unlock,则它们无法实现其目的。您可以锁定 "ClientStream" 实例,无论它是什么。
或者,使用类型对象和 ClientStream 创建一个 class、结构或元组。这样你至少可以同时拥有 Mutex 和 hte ClientStream。
刚刚测试,它按预期工作。感谢大家的热烈讨论。 运行下面的示例代码时,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");
}
}