同时为多个请求的静态成员和实例方法

时间:2012-10-25 18:50:38

标签: c# .net static

如果我将类似logger对象的对象定义为类中的static,则调用如下方法:

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

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

这是在类库项目中定义的。

我的理解是静态变量在此应用程序的所有请求之间共享,因此日志对象是共享的。但是Debug方法本身并不是静态的,但是对象是静态的,所以这个方法只有一个实例。这是对的吗?

如果很多用户同时调用此代码,如果有2个请求同时调用log.Debug方法,第二个请求的消息是否会覆盖第一个请求的消息?

此外,用Singleton替换它更好吗?不是每个请求都是一个Singleton对象吗?

这是ClientLogManager代码

  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
    }

2 个答案:

答案 0 :(得分:1)

  

如果很多用户同时调用此代码,如果有2个请求同时调用log.Debug方法,第二个请求的消息是否会覆盖第一个请求的消息?

是的,除非专门编写记录器来支持此操作。大多数记录器都是为了支持这一点而设计的,所以除非你从头开始自己动手,否则它会在内部同步所有的写入(所以你不必这样做)。如果您不确定是否应检查您正在使用的特定记录器的文档,以确定它是否会在同时写入时支持或中断。

答案 1 :(得分:0)

“我的理解是静态变量在此应用程序的所有请求之间共享,因此日志对象是共享的。” 正确的是,每个AppDomain只存在一个静态成员实例。

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

归结为:

  • 静态和实例方法在内存中只存在一次,不同之处在于 静态方法不需要为了声明它所声明的类的实例 执行,而实例方法执行。

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

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

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

在Manager类中开始声明非静态成员变量后,和 你将在Manager.Log()中使用它们,然后它不再是线程安全的: 然后,多个线程可以访问相同的Manager实例,并且可以访问它们 一切都开始写在同一个成员变量中,你遇到了麻烦......

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