如果我将像logger对象这样的对象定义为类中的静态,请调用以下方法:
public class Manager
{
private static ClientLogManager log = new ClientLogManager();
public void Log(string Message)
{
log.Debug(string Message);
}
}
这是在类库项目中定义的。
我的理解是,在此应用程序的所有请求之间共享静态变量,因此共享日志对象。但是,方法调试本身不是静态的,而是对象是静态的,因此只有一个实例。这是正确的吗?
如果许多用户同时调用此代码,如果2个请求正在调用log.debug方法,那么第二请求的消息可以覆盖第一个请求的消息?
另外,用单身人士替换它更好吗?每个请求不是一个单身对象吗?
这是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个请求正在调用log.debug方法,那么第二请求的消息可以覆盖第一个请求的消息?
是的,除非专门编写了记录器来支持这一点。大多数登录器都是为支持这一点而设计的,因此,除非您从头开始滚动的机会,否则它将同步所有内部写入(因此不必这样做)。如果您不确定,则应查看您使用的特定记录器的文档,以查看该文档是否会在同时写入时会支持或破裂。
"我的理解是,静态变量在此应用程序的所有请求之间共享,因此日志对象共享。" 正确,每个appdomain的静态成员仅有1个实例。
"但是,方法调试本身不是静态的,但是对象是静态的,所以此方法只有一个实例。这是正确的吗?" 该声明本身是正确的,但是...
它归结为:
-
静态和实例方法"存在"仅在内存中一次,区别在于静态方法不需要该类别的类实例即可被执行,而实例方法则执行。
-
如果可以同时处理多个请求,则必须在不同的线程。每个线程都有自己的调用堆栈,如果您使用线程执行方法呼叫,传递给该方法的参数放在该线程的呼叫堆栈上。
-
这意味着,只要论点是估值(例如INT)还是一个不变的类型(例如在这种情况下,字符串)不能由另一个线程修改(因为它要么是从另一个线程中看不见的,要么无法修改)。因此,您不必担心这些消息在Manager.log()或clientlogmanager.debug()方法中混合在一起。
因此,您当前的管理器和客户端logmanager实现都是线程安全的(至少,如果_log实例是线程安全的,则是线程安全。
一旦您开始在经理类中声明非静态会员变量,然后您将在Manager.log()中使用它们,而它不再是线程安全:然后可以通过多个线程访问相同的管理实例,一旦它们所有人都开始在同一成员变量中写作,您会遇到麻烦...
我希望这有点澄清。