【问题标题】:Recursion locking (i.e. a lock that works on the same thread)递归锁定(即在同一线程上工作的锁)
【发布时间】:2018-06-05 08:52:20
【问题描述】:

我想要一个锁来防止从相同线程输入一段代码,以使其更能防止无限递归。也就是说,类似于:

private static object RecurseLock = new object();
public void PartiallyRecursiveMethod()
{
    if (TryEnter(RecurseLock))
    {
        try
        {
            Console.WriteLine("Hello ");
            // we want to do it again now
            PartiallyRecursiveMethod();
        }
        finally
        {
            Release(RecurseLock);
        }
    }
    Console.WriteLine("world!");
}

这样调用PartiallyRecursiveMethod 的输出是“Hello world!”。 (或者那里可能有换行符,我忘记了Console.WriteLine 是如何工作的)

TryEnter 应该只适用于当前 线程。不应阻塞其他线程。

C# 中是否已经有一些东西可以做到这一点,还是我必须自己编写?我相信所有常见的嫌疑人(Monitor.TryEnterSemaphoreSlim 等)只会获得一个排除不同线程的锁;在这里使用它们只会导致堆栈溢出。

这需要在 .NET 2 中。

顺便说一句,我知道这个要求表明代码非常糟糕,并且真正重写代码会更明智。不过,如果 .NET 提供类似的东西,我还是很感兴趣。

【问题讨论】:

  • 您可以为此使用Semaphore 类。
  • @MatthewWatson 来自 MSDN,它说:“一个线程可以多次进入信号量”。有没有你想到的具体实现?
  • 一个简单的 ThreadLocal 布尔值将允许您执行此操作。不需要任何锁定机制。
  • @Damien_The_Unbeliever 听起来不错,不幸的是我需要它在 .NET 2 中工作(忘了提)。将更新问题。
  • @bommelding 是的,我知道。不过,我很想知道是否有任何针对此案的报价。

标签: c# .net-2.0


【解决方案1】:

正如一些人指出的那样,在 .Net 2.x 中,您可以为此使用 [ThreadStatic]

using System;
using System.Threading;
using System.Threading.Tasks;

namespace Demo
{
    class Program
    {
        static void Main()
        {
            Parallel.Invoke(test, test, test);
        }

        static void test()
        {
            if (_thisThreadAlreadyHere)
            {
                Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is already working.");
                return;
            }

            _thisThreadAlreadyHere = true;

            try
            {
                Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is working.");

                Thread.Sleep(1000);
                test();
                Thread.Sleep(1000);

                Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} has completed.");
            }

            finally
            {
                _thisThreadAlreadyHere = false;
            }
        }

        [ThreadStatic]
        static bool _thisThreadAlreadyHere;
    }
}

但是,我会说尝试以这种方式解决“无限递归”问题有些可疑。我原以为应该有更好的方法来修复逻辑 - 这似乎是一种贴膏药的方法。

【讨论】:

  • 作为一个模板,这个应该最终尝试一下,以防止出现异常时块被永久锁定。但是谢谢你,ThreadStatic 是我所追求的。
  • @Patrick 我添加了 try/finally 以防其他人将此答案用于任何事情。
猜你喜欢
  • 2016-08-07
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多