我试图了解C#中的监视器,并尝试了以下程序。
基本上,这就是它试图做的全部:
线程1获取对象的锁定(在方法m中完成)
线程2调用另一个方法,当线程1仍然保持锁定时,该方法更改锁定对象的状态。(主线程通过调用anotherMethod来执行此操作)
理想情况下,人们会期望当一个对象上有一个锁时,没有其他线程可以在锁的生命周期内改变它的状态。但这似乎并没有发生。
class Program
{
private int x = 0;
void Method()
{
lock (this)
{
Thread.Sleep(5000);
}
}
void AnotherMethod()
{
x++;
Console.WriteLine("entered");
}
static void Main(string[] args)
{
Program p = new Program();
Thread t = new Thread(() => p.Method());
t.Start();
p.AnotherMethod();
}
}
如果锁定在生效时没有冻结对象的状态,那么它有什么用?
另外,请帮助我理解这一点:如果锁定语句的唯一目的是将某些代码标记为关键部分,那么获取锁定对象的重要性是什么?
答案 0 :(得分:0)
你真的可能想要了解多线程编程(以及它的缺陷)。
所有锁定都是获取互斥锁 - 互斥信号。这意味着没有其他线程应用程序获得相同的互斥锁,直到当前所有者放弃它。
除了双方同意之外没有任何意义。所有lock
语句都意味着一旦资源被锁定,其他线程尝试通过lock
尝试获取相同的资源将无法执行此操作直到拥有线程放弃对资源的控制。
由于您的m()
方法使用lock
但anotherMethod()
未使用,anotherMethod()
完全不知道锁的存在。
此外,您可能希望阅读以下问题: Why is lock(this) {...} bad?
答案 1 :(得分:0)
锁定将锁定对象的实例。您似乎在静态方法中创建了程序的新实例?所以你已经锁定了静态实例。这与您的p实例不同。使用锁的最佳方法是定义单独的对象以锁定共享类。如果锁定实现类,可能会遇到并发问题。
例如,锁定对我班级中特定代码块的访问。
public class SharedCounter
{
Object lockObj = new Object();
Private int count =0;
public void Increment()
{
Lock(lockObj)
{
count++;
}
}
}
现在你可以安全地将这个类的一个实例传递给多个线程,并且当每个线程调用increment时,计数会安全地递增。(虽然这个例子你会使用interlocked,因为它只是增加一个int)
但希望这是有道理的。