如果我将类似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
}
答案 0 :(得分:1)
如果很多用户同时调用此代码,如果有2个请求同时调用log.Debug方法,第二个请求的消息是否会覆盖第一个请求的消息?
是的,除非专门编写记录器来支持此操作。大多数记录器都是为了支持这一点而设计的,所以除非你从头开始自己动手,否则它会在内部同步所有的写入(所以你不必这样做)。如果您不确定是否应检查您正在使用的特定记录器的文档,以确定它是否会在同时写入时支持或中断。
答案 1 :(得分:0)
“我的理解是静态变量在此应用程序的所有请求之间共享,因此日志对象是共享的。” 正确的是,每个AppDomain只存在一个静态成员实例。
“但是Debug方法本身并不是静态的,但是对象是静态的,所以这个方法只有一个实例。这是正确的吗?” 声明本身是正确的,但是......
归结为:
静态和实例方法在内存中只存在一次,不同之处在于 静态方法不需要为了声明它所声明的类的实例 执行,而实例方法执行。
如果可以同时处理多个请求,则必须在不同的请求上执行 线程。每个线程都有自己的调用堆栈,如果使用线程执行方法 调用,传递给该方法的参数放在该线程的调用堆栈上。
这意味着,只要参数是值类型(例如int)或者 不可变类型(例如在这种情况下,一个字符串)它不能被另一个线程修改 (因为它从另一个线程看不到,或者不可修改)。 因此,您不必担心消息会在Manager.Log()或ClientLogManager.Debug()方法中混淆。
因此,您当前的Manager和ClientLogManager实现都是线程安全的(至少,如果_log实例是线程安全的)。
在Manager类中开始声明非静态成员变量后,和 你将在Manager.Log()中使用它们,然后它不再是线程安全的: 然后,多个线程可以访问相同的Manager实例,并且可以访问它们 一切都开始写在同一个成员变量中,你遇到了麻烦......
我希望这会澄清一些事情。