如何使类线程安全我正在编写一个C#应用程序。我有(某种)日志类。而且很多多线程都会用到这个日志类。如何使此类线程安全?我应该让它成为单身人士吗?最佳做法是什么?有没有我可以阅读的关于如何使其线程安全的文档?谢谢在C#中,任何对象都可以用来保护“临界区”,换句话说,代码不能同时由两个线程执行。例如,以下将同步对SharedLogger.Write方法的访问,因此在任何给定时间只有一个线程在记录消息。公共类SharedLogger:ILogger{publicstaticSharedLoggerInstance=newSharedLogger();publicvoidWrite(strings){lock(_lock){_writer.Write(s);}}privateSharedLogger(){_writer=newLogWriter();}私有对象_lock;私有LogWriter_writer;我会使用现成的记录器,因为有几个非常坚固且易于使用。无需自己动手。我推荐Log4Net。我不确定我是否可以添加任何关于使日志记录类线程安全的内容。如前所述,要做到这一点,您必须同步对资源(即日志文件)的访问,以便一次只有一个线程尝试登录它。C#lock关键字是执行此操作的正确方法。但是,我将讨论(1)单例方法和(2)您最终决定使用的方法的可用性。(1)如果您的应用程序将其所有日志消息写入单个日志文件,那么单例模式绝对是可行的方法。日志文件将在启动时打开并在关闭时关闭,单例??模式非常适合这种操作理念。正如@dtb指出的那样,请记住,将类设为单例并不能保证线程安全。使用锁定关键字。(2)至于方法可用性,考虑以下建议的解决方案:publicclassSharedLogger:ILogger{publicstaticSharedLoggerInstance=newSharedLogger();publicvoidWrite(strings){lock(_lock){_writer.Write(s);}}privateSharedLogger(){_writer=newLogWriter();}私有对象_lock;私有LogWriter_writer;让我先说这种方法通常很好。它通过Instance静态变量定义了SharedLogger的单例实例,并防止其他人通过私有构造函数实例化该类。这是单例模式的本质,但我强烈建议在走得太远之前阅读并遵循JonSkeet关于C#单例的建议。然而,我想关注的是这个解决方案的可用性。“可用性”是指使用此实现记录消息的方式。考虑调用的样子:SharedLogger.Instance.Write("logmessage");整个“实例”部分看起来不对,但考虑到实现,没有办法避免它。相反,请考虑以下替代方案:publicstaticclassSharedLogger:ILogger{privatestaticLogWriter_writer=newLogWriter();私有静态对象_lock=newobject();publicstaticvoidWrite(strings){lock(_lock){_writer.写;}}}请注意,该类现在是静态的,这意味着它的所有成员和方法都必须是静态的。它与前面的示例没有本质区别,但请考虑它的用法。SharedLogger.Write("日志信息");这样编码起来就简单多了。重点不是诋毁前一种解决方案,而是建议您选择的任何解决方案的可用性是一个不容忽视的重要方面。一个好的、可用的API使代码编写更简单、更优雅、更易于维护。使用lock()让多个线程不会同时使用日志根据BCS的回答:BCS描述的是无状态对象的情况。这样的对象本质上是线程安全的,因为它没有自己的变量,这些变量可以被来自不同thead的调用销毁。所描述的记录器确实有一个文件句柄(抱歉,不是C#用户,可能它被称为IDiskFileResource或类似的MS-ism),必须序列化才能使用。因此,将消息的存储与将它们写入日志文件的逻辑分开。逻辑一次只能对一条消息进行操作。一种方法是:如果记录器对象要保留一个消息对象队列,而记录器对象只有从队列中弹出消息的逻辑,从消息对象中提取一些有用的东西,将其写入日志,然后添加它在队列中查找另一条消息-然后您可以通过使线程安全来使队列的添加/删除/queue_size/etc操作线程安全。它需要一个记录器类、一个消息类和一个线程安全队列(可能是第三个类,其实例是记录器类的成员变量)。在我看来,上面提供的代码不再是线程安全的:在以前的解决方案中,您必须为SharedLogger创建一个新对象,并为每个对象设置一次Write方法。现在你只有一个Write方法,它被所有线程使用,例如:Thread1:SharedLogger.Write("Thread1")Thread2:SharedLogger.Write("Thread2");publicstaticvoidWrite(strings){//thread1isinterruptedhere当我错了时纠正我...如果性能不是主要问题,例如,如果类没有很多负载,请执行this:让你的类inheritContextBoundObject将这个属性应用到你的类class[synchronized]你的整个类现在一次只能由一个线程访问。这对于诊断来说真的更有用,因为速度方面它几乎是最坏的情况......但很快决定“这是一个奇怪的问题是竞争条件”,扔掉它,重新运行测试......如果问题走了......你知道这是一个线程问题......一个更有效的选择是让你的日志类有一个线程安全的消息队列(接受日志消息,然后将它们拉出来并按顺序处理它们......例如新的并行化内容中的ConcurrentQueue类是一个很好的线程安全队列。或者用户log4netRollingLogFileAppender,它已经是线程安全的。以上就是C#学习教程的全部内容:如何使类线程安全分享,如果有用送给大家和需要了解更多C#学习教程,希望大家多多关注---本文收集自网络,不代表立场,如涉及侵权,请点击右边联系管理员删除,如需转载请注明出处:
