2

If I define an object like a logger object as static in a class, then call a method like the following:

public class Manager
{    
    private static ClientLogManager log = new ClientLogManager();

    public void Log(string Message)
    {
         log.Debug(string Message);
    }
}

This is defined in a class library project.

My understanding is that the static variable is shared between all requests for this application, so the log object is shared. However the method Debug itself is not static, but the object is static, so there will be only one instance of this method. Is that correct?

If a lot of users are calling this code at the same time, if 2 requests are calling the log.Debug method at the same time, can the message of the 2nd request overwrite the message of the 1st request?

Also, is it better to replace this with a Singleton? wouldn't it be one Singleton object per request?

Here is the ClientLogManager code

  public class ClientLogManager
    {
        #region Member Variables

        private static readonly ILog _log = LogManager.GetLogger(typeof(ClientLogManager));

        #endregion

        #region Constructors

        public ClientLogManager()
        {

        }

        #endregion

        #region Public Methods

        public void Debug(string message)
        {
            _log.Debug(message);
        }

        #endregion
    }
4

2 回答 2

1

如果很多用户同时调用这段代码,如果2个请求同时调用log.Debug方法,那么第2个请求的消息会覆盖第1个请求的消息吗?

是的,除非记录器是专门为支持这一点而编写的。大多数记录器都旨在支持这一点,因此除非您从头开始创建自己的记录器,否则它可能会在内部同步所有写入(这样您就不必这样做)。如果您不确定是否应该检查您正在使用的特定记录器的文档,以查看它在同时写入时是否支持或中断。

于 2012-10-25T19:06:10.370 回答
0

“我的理解是,这个应用的所有请求都共享静态变量,所以共享日志对象。” 正确,每个 AppDomain 仅存在 1 个静态成员实例。

“但是Debug方法本身不是静态的,对象是静态的,所以这个方法的实例只有一个,对吗?” 声明本身是正确的,但是...

它归结为:

  • 静态方法和实例方法都只在内存中“存在”一次,区别在于静态方法不需要声明它的类的实例才能执行,而实例方法则需要。

  • 如果可以同时处理多个请求,则它们必须在不同的线程上执行。每个线程都有自己的调用堆栈,如果您使用线程执行方法调用,则传递给该方法的参数将放置在该线程的调用堆栈中。

  • 这意味着,只要参数是值类型(例如 int)或不可变类型(例如在本例中为字符串),它就不能被另一个线程修改(因为它要么对另一个线程不可见,或不可修改)。因此,您不必担心消息会在 Manager.Log() 或 ClientLogManager.Debug() 方法中混淆。

因此,您当前的 Manager 和 ClientLogManager 实现都是线程安全的(至少,如果 _log 实例是线程安全的)。

一旦你开始在你的 Manager 类中声明非静态成员变量,并且你将在 Manager.Log() 中使用它们,那么它就不再是线程安全的:同一个 Manager 实例可以被多个线程访问,一旦他们都开始在同一个成员变量中写入,你就有麻烦了......

我希望这能澄清一些事情。

于 2012-10-25T19:17:29.147 回答