如果我想的话,请告诉我。
其他线程无法使用相同的关键部分
同一个锁只是因为第一个线程叫Monitor.Wait
,对吗? Wait
方法仅允许获取不同的线程
相同的监视器,即相同的同步锁,但仅用于不同的关键部分,从不用于相同的关键部分
节
我的理解是否正确?
因为如果Wait
方法意味着任何人现在都可以输入
使用同一个锁的同一个关键部分,然后就会失败
同步的整个目的,对吧?
所以,在下面的代码中(写在记事本中,所以请原谅任何
错别字),ThreadProc2
只能使用syncLock
输入代码
ThreadProc2
而不是前一个帖子中的ThreadProc1
持有并随后放弃锁定正在执行
ThreadProc1
,对吧?
两个或多个线程可以使用相同的同步锁来运行 不同的代码片段在同一时间,对吧?同样的问题 以上,基本上,只是为了对称而确认 第3点。
两个或多个线程可以使用不同的同步锁 运行相同的代码,即进入相同的关键部分。
用于更正格式的Boilerplate文本。
class Foo
{
private static object syncLock = new object();
public void ThreadProc1()
{
try
{
Monitor.Enter(syncLock);
Monitor.Wait(syncLock);
Thread.Sleep(1000);
}
finally
{
if (Monitor.IsLocked(syncLock))
{
Monitor.Exit(syncLock);
}
}
}
public void ThreadProc2()
{
bool acquired = false;
try
{
// Calling TryEnter instead of
// Enter just for the sake of variety
Monitor.TryEnter(syncLock, ref acquired);
if (acquired)
{
Thread.Sleep(200);
Monitor.Pulse(syncLock);
}
}
finally
{
if (acquired)
{
Monitor.Exit(syncLock);
}
}
}
}
更新
以下插图证实了#3是正确的,尽管我认为这不是一件好事。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace DifferentSyncLockSameCriticalSection
{
class Program
{
static void Main(string[] args)
{
var sathyaish = new Person { Name = "Sathyaish Chakravarthy" };
var superman = new Person { Name = "Superman" };
var tasks = new List<Task>();
// Must not lock on string so I am using
// an object of the Person class as a lock
tasks.Add(Task.Run( () => { Proc1(sathyaish); } ));
tasks.Add(Task.Run(() => { Proc1(superman); }));
Task.WhenAll(tasks);
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
static void Proc1(object state)
{
// Although this would be a very bad practice
lock(state)
{
try
{
Console.WriteLine((state.ToString()).Length);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
class Person
{
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
}
答案 0 :(得分:4)
当一个线程调用Monitor.Wait
时,它被挂起并释放锁。这将允许另一个线程获取锁,更新某个状态,然后调用Monitor.Pulse
以便与其他线程通信已发生的事情。您必须已获得锁定才能拨打Pulse
。在Monitor.Wait
返回之前,框架将重新获取调用Wait
。
为了使两个线程相互通信,它们需要使用相同的同步原语。在您的示例中,您使用了监视器,但通常需要将此与Wait
为响应Pulse
而返回的某种测试结合使用。这是因为即使Wait
没有被调用,Pulse
在技术上也可以返回(尽管在实践中这不会发生)。
还值得记住,对Pulse
的调用不是“粘性”,因此如果没有人在监视器上等待,那么Pulse
什么都不做,随后对Wait
的调用将会想念Pulse
被召唤的事实。这是为什么你倾向于在调用Pulse
之前记录已完成某事的事实的另一个原因(参见下面的例子)。
两个不同的线程使用相同的锁来运行不同的代码完全有效 - 实际上这是典型的用例。例如,一个线程获取锁以写入一些数据,另一个线程获取锁以读取数据。但是,重要的是要意识到它们不会同时运行。获取锁的行为会阻止另一个线程获取相同的锁,因此任何尝试获取锁的线程都将被锁定,直到另一个线程释放锁。
在第3点,你问:
两个或多个线程可以使用不同的同步锁来运行 相同的代码,即进入相同的关键部分。
但是,如果两个线程使用不同的锁,则它们不会进入相同的关键部分。关键部分由保护它的锁表示 - 如果它们是不同的锁,则它们是碰巧访问该部分内的一些公共数据的不同部分。您应该避免这样做,因为它可能导致一些难以调试的数据竞争条件。
对于您要完成的任务,您的代码有点过于复杂。例如,假设我们有2个线程,当有可供另一个处理的数据时,一个线程会发出信号:
class Foo
{
private readonly object syncLock = new object();
private bool dataAvailable = false;
public void ThreadProc1()
{
lock(syncLock)
{
while(!dataAvailable)
{
// Release the lock and suspend
Monitor.Wait(syncLock);
}
// Now process the data
}
}
public void ThreadProc2()
{
LoadData();
lock(syncLock)
{
dataAvailable = true;
Monitor.Pulse(syncLock);
}
}
private void LoadData()
{
// Gets some data
}
}
}