gpt4 book ai didi

c# - 使用相同的锁修改锁内的对象

转载 作者:太空宇宙 更新时间:2023-11-03 14:23:33 25 4
gpt4 key购买 nike

我有一个由工作项集合组成的工作对象。每个作业都有自己的 WatcherClass 与之关联,它经常检查数据库以查看是否需要取消执行。它可以在工作流中的任何迭代中取消。如果它被取消,从 foreach block 运行的任何线程都将传播取消并正常退出。

我的观察程序代码中是否存在任何可能造成死锁的问题?我试图通过使用 Timer.Change(Timeout.Infinite, Timeout.Infinite) 只允许一个线程处理计时器回调,但事实上我正在锁内更改 WatcherClass.Job语句破坏了锁的目的(因为我将 _Job 的相同 get/set 包装在同一个锁对象中)?代码似乎运行良好,但我知道这并不能说明任何问题。

主线程中的代码看起来与此类似:

using (WatcherClass watcher = new WatcherClass())
{
watcher.CancelTokenSource = new CancellationTokenSource();
watcher.Start();
foreach (SomeJob job in worksflow.Jobs)
{
watcher.Job = job;
//Do some stuff async
//Do some more stuff async
}

}

public class WatcherClass : IDisposable
{
private System.Threading.Timer _WatcherTimer;
private readonly object locker = new object();
private bool _Disposed = false;
private SomeJob _Job;

public SomeJob Job
{
get
{
lock (locker)
{
return _Job;
}
}
set
{
lock (locker)
{
_Job= value;
}
}
}

public System.Threading.Task.CancellationTokenSource
CancelToken { get; set; }

public WatcherClass()
{
_WatcherTimer = new Timer(new TimerCallback(DoCheck), null,
Timeout.Infinite, Timeout.Infinite);
}

public void Start()
{
_WatcherTimer.Change(30000, Timeout.Infinite);
}

public void DoCheck(object state)
{

lock (locker)
{

if (_Disposed || this.CancelToken.IsCancellationRequested)
return;

_WatcherTimer.Change(Timeout.Infinite, Timeout.Infinite);

//Check database to see if task is cancelled
if (cancelled)
{
this.CancelToken.Cancel();
_Job.CancelResult = CancelResult.CanceledByUser;
_Job.SomeOtherProperty = true;
}
else
{
//Safe to continue
_WatcherTimer.Change(30000, Timeout.Infinite);
}
}

}

public void Dispose(bool disposing)
{
lock (locker)
{
if (disposing)
{
if (_WatcherTimer != null)
_WatcherTimer.Dispose();

}
_Disposed = true;
}
}
}

最佳答案

您在 Task 属性和 DoCheck 函数中获取的锁仅保护对 WatcherClass 的内部 _task 字段的访问。在 DoCheck 中,您还修改了 _task 对象本身的属性。该锁不会阻止任何其他人同时从其他线程修改任务对象的字段。

如果在您的应用程序中任务对象仅由 DoCheck 操作,那么您可能没问题。如果任务对象可能由 DoCheck 以外的代码操作,那么您可能会遇到问题。

另请记住,您创建的每一个额外的锁都是死锁的额外机会。如果始终以特定顺序获取多个锁,则它们可以是无死锁的。如果代码流允许在某些情况下在锁 B 之前获取锁 A,或者在其他情况下在锁 A 之前获取锁 B,那么您将面临严重的死锁风险。 (线程 1 锁定 A,尝试锁定 B,而线程 2 锁定 B 并尝试锁定 A => 死锁)

在您的 WatcherClass 案例中,如果您打算拥有多个 watcherclass 实例,每个实例都有自己的锁,请注意不要进行可能最终尝试获取其他 watcherclass 实例中的锁的外部调用(或触发事件)。这是等待发生的 AB/BA 僵局。

关于c# - 使用相同的锁修改锁内的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4694911/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com