c#-第二个线程能否仅因为第一个线程名为Monitor.Wait使用相同的同步锁而进入相同的临界区?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c#-第二个线程能否仅因为第一个线程名为Monitor.Wait使用相同的同步锁而进入相同的临界区?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3924字,纯文字阅读大概需要6分钟。
内容图文
![c#-第二个线程能否仅因为第一个线程名为Monitor.Wait使用相同的同步锁而进入相同的临界区?](/upload/InfoBanner/zyjiaocheng/683/58ee74665c0b44d39c5d7a366f1bd9cc.jpg)
请告诉我我是否认为还好.
>不同的线程无法使用以下命令进入相同的关键部分
相同的锁只是因为第一个线程名为Monitor.Wait,对吧? Wait方法仅允许其他线程获取
相同的监视器,即相同的同步锁,但仅用于不同的关键部分,而从不用于相同的关键
部分.
我的理解正确吗?
因为如果Wait方法意味着任何人现在都可以输入
使用相同的锁的同一关键部分,那么那将失败
整个同步的目的,对不对?
因此,在下面的代码中(用记事本编写,因此请原谅
错别字),ThreadProc2只能使用syncLock在以下位置输入代码
ThreadProc2而不是ThreadProc1,而上一个线程
持有并随后放弃执行锁
ThreadProc1,对吗?
>两个或更多线程可以使用相同的同步锁来运行
可以同时使用不同的代码,对吗?与相同的问题
上面,基本上,但是只是为了与
下面的第3点.
>两个或更多线程可以使用不同的同步锁来
运行相同的代码段,即输入相同的关键部分.
样板文字以更正格式.
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;
}
}
}
解决方法:
当线程调用Monitor.Wait时,它将挂起并释放锁.这将允许另一个线程获取锁,更新某些状态,然后调用Monitor.Pulse以便与其他线程进行通信.您必须已获取锁才能调用Pulse.在Monitor.Wait返回之前,框架将重新获取名为Wait的线程的锁.
为了使两个线程彼此通信,它们需要使用相同的同步原语.在您的示例中,您使用了监视器,但是通常需要将此监视器与Wait响应Pulse所返回的某种测试结合起来.这是因为从技术上讲,即使未调用Pulse,也可以等待返回(尽管实际上没有发生).
还值得记住的是,对Pulse的调用不是“粘性”的,因此,如果没有人在监视器上等待,则Pulse不会执行任何操作,而随后对Wait的调用将错过调用Pulse的事实.这就是为什么您倾向于记录在调用Pulse之前已完成某件事的事实的另一个原因(请参见下面的示例).
两个不同的线程使用相同的锁来运行不同的代码位是完全有效的-实际上,这是典型的用例.例如,一个线程获取锁以写入一些数据,而另一个线程获取锁以读取数据.但是,重要的是要意识到它们不能同时运行.获取锁的行为阻止了另一个线程获取相同的锁,因此,任何试图在已被锁定时获取锁的线程都将阻塞,直到另一个线程释放锁为止.
在第3点中,您要求:
Two or more threads can use a different synchronization lock to run
the same piece of code, i.e. to enter the same critical section.
但是,如果两个线程使用不同的锁,则它们不会进入相同的关键部分.关键部分由保护它的锁来表示-如果它们是不同的锁,则它们是恰好访问该部分中某些公共数据的不同部分.您应该避免这样做,因为这可能会导致调试数据竞争条件变得困难.
对于您要完成的工作,您的代码有些复杂.例如,假设我们有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
}
}
}
内容总结
以上是互联网集市为您收集整理的c#-第二个线程能否仅因为第一个线程名为Monitor.Wait使用相同的同步锁而进入相同的临界区?全部内容,希望文章能够帮你解决c#-第二个线程能否仅因为第一个线程名为Monitor.Wait使用相同的同步锁而进入相同的临界区?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。