【问题标题】:Why are loggers static?为什么记录器是静态的?
【发布时间】:2021-02-12 10:00:23
【问题描述】:

我想知道为什么像 NLog 这样的 Logger 有一个静态实现?
据我了解,使用“静态”通常是不好的做法,因为它会阻止多线程。

我知道我们想要阻止多个方法同时访问同一个记录器,但是这样做,我们不是也阻止了不同的记录器并行运行吗?

有什么我没有得到的吗?

这是一个强调问题的代码示例:

public static class LogUtils
{     
    ...
       
    public static void SetupLogging(string appName, string logFileName)
    {
        var target = (FileTarget)LogManager.Configuration.FindTargetByName("f");

        _logFileName = string.IsNullOrEmpty(logFileName) ? GetFileName(appName): logFileName;
        target.FileName = _logFileName;
        LogManager.ReconfigExistingLoggers();
    }
}

【问题讨论】:

  • 静态不会阻止多线程。修改共享状态可以 =)
  • 不,static 不会阻止多个线程同时启动。 lock 确实如此。
  • 我所知道的所有日志框架都是线程安全的:如果不是,那将是一个糟糕的日志框架!他们在内部处理这个问题的方式各不相同(有时是可配置的),但您可以确信您可以使用静态 LogManager 来获取两个记录器并同时从两个线程中使用它们
  • 通常,您希望所有日志记录都转到单个日志输出,因此这是默认设置。但是你可以在 NLog 中使用多个记录器:你需要在配置文件中指定多个记录器,然后使用LogManager.GetLogger() 来获取它们。所以虽然LogManager.GetLogger() 是静态的,但它返回的记录器显然不是静态类。
  • @00110001 将 DI 与记录器一起使用不一定是一个好主意,因为它涉及跨领域问题。尽管如此,完全可以将 DI 与 NLog 一起使用。

标签: c# multithreading logging


【解决方案1】:

Static 绝不保证线程安全。假设您有一个写入文件的静态方法:

static Write() { myFile.WriteChanges; }

现在,当多个线程访问该方法时,它们会同时写入完全相同的文件 - 这将是一团糟。这就是lock-关键字存在的原因:

static Write() { lock(whatever) myFile.WriteChanges; }

现在只有一个线程可以访问相同的资源。其他人必须等待。

logging-Managers 没有任何不同。通常,您希望所有日志记录都转到同一个文件,因此它们以某种方式依赖于该共享资源的内部锁定。但是,这与经理本身是单身人士无关。您也可以从记录器的多个实例中锁定特定资源。

简而言之:static 仅表示调用特定成员时不涉及任何实例。另一方面,lock 专注于共享资源,例如文件。这两件事没有任何共同点。

【讨论】:

    【解决方案2】:

    因为日志记录是作为SingleTon 实现的,这意味着,无论在任何给定时间有多少对象在使用它,您都应该拥有 1 个且只有 1 个记录器实例。

    【讨论】:

    • 这和多线程有什么关系?
    • @HimBromBeere 什么都没有......这就是为什么我没有在我写的答案中提到它,......
    • 但是 OP 专门要求多线程,而不是 static 的意思——尽管这会导致 OP 误解。
    • 另外,问题是关于static,而不是singleton
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 2023-04-04
    • 1970-01-01
    相关资源
    最近更新 更多