zoukankan      html  css  js  c++  java
  • 单例模式与方法的同步异步

    项目功能需求:

    添加一个log记录工具类,将每天的log信息分别记入新建的文本文件中。(要求自己写一个简单实现,不借助第三方类库)。
    首先想法:应log工具类需要访问文本资源,将其设计为单例模式,以避免多线程访问同一资源报异常。

    public class TextLogger
    	{
    		private static string _logPath = Path.Combine(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath, "Logs\Log\");
    		
    		private static TextLogger _instance = null;
    
    		public static TextLogger Instance
    		{
    			get
    			{
    				if (_instance == null)
    				{
    					_instance = new TextLogger();
    				}
    				return _instance;
    			}
    		}
    
    		private TextLogger()
    		{
    			if (!Directory.Exists(_logPath))
    			{
    				Directory.CreateDirectory(_logPath);
    			}
    		}
    
    		public void WriteLog(string message)
    		{
    			try
    			{
    				using (StreamWriter sw = new StreamWriter(_logPath + DateTime.Today.ToString("yyyy-MM-dd") + ".log", true))
    				{
    					sw.WriteLine(DateTime.Now.ToString("HH:mm:ss.fffff") + "	" + message);
    				}
    			}
    			catch
    			{
    			}
    		}
    	}
    

    使用TextLogger工具,TextLogger.Instance.WriteLog("Application_Start Begin");,在单线程下可以正常工作,但到了多线程下会偶然报bug,该怎么解决呀?

    理清概念:

    • 单例模式:保证的是在多线程下,该类只存在唯一的对象(不能保证,对象的某个方法之被单线程调用)
    • 方法的同步异步:从概念上理解同步与异步与是否多线程没有关系,但在.net,异步的实现本质上是:执行耗时操作时,为消除当前线程的阻塞,开启新的线程执行其他任务。(所以在方法中保证同步执行需要加锁lock)

    举个测试小栗子,在控制中新建

    class SyncHelper
    {
        public void Execute()
        {
            Console.WriteLine("Excute at {0}", DateTime.Now);
            Thread.Sleep(5000);
        }
    } 
    

    Main函数

      class Program
      {
          static void Main(string[] args)
          {
              SyncHelper helper = new SyncHelper();
              Timer timer = new Timer(
              delegate
              {
                  helper.Execute();
              }, null, 0, 1000); 
       
              Console.Read(); 
       
          }
      } 
    

    执行发现,每个1s打印异常而非5s。在Execute()方法上添加Attribute线程锁[MethodImpl(MethodImplOptions.Synchronized)]在执行发现输出将为5s。

    • [MethodImplAttribute(MethodImplOptions.Synchronized)]仍然采用加锁的机制实现线程的同步。
    • 如果[MethodImplAttribute(MethodImplOptions.Synchronized)]被应用到instance method,相当于对当前实例加锁。
    • 如果[MethodImplAttribute(MethodImplOptions.Synchronized)]被应用到static method,相当于当前类型加锁

    结论

    所以最简单的解决方法:在TextLogger.WriteLog方法上添加[MethodImpl(MethodImplOptions.Synchronized)]

    参考自[MethodImpl(MethodImplOptions.Synchronized)]、lock(this)与lock(typeof(...))

  • 相关阅读:
    【深度学习】RNN | GRU | LSTM
    深度学习中优化【Normalization】
    Transformer【Attention is all you need】
    假期第二十三天加机器学习十讲二
    假期第二十二天加机器学习十讲一
    《架构之美》读书笔记二
    假期第二十一天
    假期第二十天
    假期第十九天
    假期第十八天
  • 原文地址:https://www.cnblogs.com/LoveTomato/p/10300287.html
Copyright © 2011-2022 走看看