gpt4 book ai didi

c# - 第二个线程在第一个线程释放之前进入锁

转载 作者:行者123 更新时间:2023-11-30 14:26:55 25 4
gpt4 key购买 nike

我正在使用 C# 中的一些线程结构,遇到了一些违背我对锁定工作原理的理解的东西。我有一个接受异步任务的辅助函数,并使用 TaskCompletionSource 成员在多次调用时尝试同步访问。

public static void Main(string[] args)
{
var test = new TestClass();
var task1 = test.Execute("First Task", async () => await Task.Delay(1000));
var task2 = test.Execute("Second Task", async () => await Task.Delay(1000));

task1.Wait();
task2.Wait();

Console.ReadLine();
}

class TestClass : IDisposable
{
private readonly object _lockObject = new object();
private TaskCompletionSource<bool> _activeTaskCompletionSource;

public async Task Execute(string source, Func<Task> actionToExecute)
{
Task activeTask = null;
lock (_lockObject)
{
if (_activeTaskCompletionSource != null)
{
activeTask = _activeTaskCompletionSource.Task;
}
else
{
_activeTaskCompletionSource = new TaskCompletionSource<bool>();
}
}

while (activeTask != null)
{
await activeTask;
lock (_lockObject)
{
if (_activeTaskCompletionSource != null)
{
activeTask = _activeTaskCompletionSource.Task;
}
else
{
activeTask = null;
}
}
}

await actionToExecute();
lock (_lockObject)
{
_activeTaskCompletionSource.SetResult(true);
_activeTaskCompletionSource = null;
}
}
}

这总是会陷入第二个任务的无限循环。我放了一些代码来记录每个步骤,它总是产生这样的结果(我在#s 之后手动插入注释):

[First Task] Waiting for lock (setup)[First Task] Entered lock (setup)[First Task] Grabbing '_activeTaskCompletionSource' (setup)[First Task] Lock released (setup)[First Task] RUNNING ...[Second Task] Waiting for lock (setup)[Second Task] Entered lock (setup)[Second Task] Assigning 'activeTask' (setup)[Second Task] Lock released (setup)[Second Task] Waiting for task to complete ...[First Task] COMPLETED![First Task] Waiting for lock (cleanup)[First Task] Entered lock (cleanup)[First Task] Setting _activeTaskCompletionSource result ...    # Never gets to '_activeTaskCompletionSource = null'    # Never gets to 'Releasing lock (cleanup)' for first task[Second Task] Awaited task completed![Second Task] Waiting for lock (loop)    # Immediately enters lock after 'await' is complete    # Does not wait for 'First Task' to finish its lock![Second Task] Entered lock (loop)[Second Task] Assigning 'activeTask' (loop)[Second Task] Lock released (loop)[Second Task] Waiting for task to complete ...[Second Task] Awaited task completed!

这最终将第二个任务发送到无限循环中,因为 _activeTaskCompletionSource 永远不会设置回 null

我的印象是没有其他线程在所有以前的线程都退出之前永远不会进入锁,但是在这里,我的First Task线程永远不会完成并释放在 Second Task 线程获取它之前它的清理锁。

这与混合锁和异步/等待有什么关系吗?

最佳答案

调用 TaskCompletionSource.SetResult 可以内联延续,导致意外和任意代码在锁定下运行。 await 也使用延续。

这种讨厌的行为是 TPL 中的一个设计错误。如果你关心这个there is a GitHub issue .在那里发表评论。

关于c# - 第二个线程在第一个线程释放之前进入锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34295094/

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