单例模式与方法的同步异步

项目功能需求:

添加一个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") + "\t" + 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(...))

转载于:https://www.cnblogs.com/LoveTomato/p/10300287.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值