c#多线程lock无效

 在写windows服务的时候需要用到多线程跑数据,执行方法中用lock锁住一段代码,记录日志后发现无效,没起作用。

 program 代码如下:

/// <summary>
        /// 应用程序的主入口点
        /// </summary>
        static void Main()
        {
            Log4Helper.GetInstance().Info("服务启动");
            try
            {
                ThreadPool.QueueUserWorkItem(PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(PushCache, new SearchParam() { MsgType = 3 });
                TimeSpan sleepTime = new TimeSpan(1, 0, 0); //休眠一小时
                while (true)
                {
                    Thread.Sleep(sleepTime);
                }
            }
            catch (Exception e)
            {
                Log4Helper.GetInstance().Error(e);
            }
        }

public static void PushCache(object obj)
        {
            var search = obj as SearchParam;
            MessageCacheBll.GetInstance().PushCache(search);
        }


public class SearchParam
{
/// <summary>
/// 消息类型
/// </summary>
public int MsgType { get; set; }
}

 

MessageCacheBll类方法如下:

public class MessageCacheBll
    {
        private readonly object _lockThread = new object();

        #region Instance

        private static MessageCacheBll _instance;

        public static MessageCacheBll GetInstance()
        {
            return _instance ?? (_instance = new MessageCacheBll());
        }

        #endregion

        /// <summary>
        /// 按照消息类型和学段跑数据
        /// </summary>
        /// <param name="search">msgType消息类型</param>
        public void PushCache(object obj)
        {
            var search = (obj as SearchParam) ?? new SearchParam();
            try
            {
                var sqlWhere = "";
                if (search.MsgType == -1)
                {
                    sqlWhere += " and spm.type in(1,3,4,5,6,100) ";//1系统消息、3消息、4作业、5成绩通知、6请假、100成绩通知的发件箱用
                }
                else
                {
                    sqlWhere += string.Format(" and spm.type={0} ", search.MsgType);
                }
                List<SpMessageDto> list = new List<SpMessageDto>();
                var updateCacheStatusResult = false;//更新缓存状态结果
                //锁 获取当前线程要跑的数据
                try
                {
                    lock (_lockThread)
                    {
                        Log4Helper.GetInstance().Info(string.Format("--------lock-开始 threadid{0}--------",
                            Thread.CurrentThread.ManagedThreadId));
                        list = MessageCacheDal.GetInstance().GetNoCacheMessageList(sqlWhere);
                        if (list != null && list.Count > 0)
                        {
                            var idList = list.Select(t => t.Id).ToList();
                            updateCacheStatusResult = MessageCacheDal.GetInstance()
                                .UpdateMessageCacheStatus((int)AppEnum.CacheStatus.Caching, idList);
                        }

                        Log4Helper.GetInstance().Info(string.Format("--------lock-结束 threadid{0}--------",
                            Thread.CurrentThread.ManagedThreadId));
                    }
                }
                catch (Exception e)
                {
                    Log4Helper.GetInstance().Error(e);
                }
            }
            catch (Exception e)
            {
                Log4Helper.GetInstance().Error(string.Format("异常 msgType:{0}。", search.MsgType), e);
            }
        }
    }
}

日志输出结果:

2020-01-01 11:36:02,872 服务启动

2020-01-01 11:36:02,882 --------lock-开始 threadid4--------

2020-01-01 11:36:02,884 --------lock-开始 threadid5--------

2020-01-01 11:36:02,884 --------lock-开始 threadid7--------

2020-01-01 11:36:02,884 --------lock-开始 threadid3--------

2020-01-01 11:36:03,325 --------lock-结束 threadid3--------

2020-01-01 11:36:03,363 --------lock-结束 threadid7--------

2020-01-01 11:36:03,367 --------lock-结束 threadid4--------

2020-01-01 11:36:03,368 --------lock-开始 threadid6--------

2020-01-01 11:36:03,370 --------lock-结束 threadid5--------

2020-01-01 11:36:03,595 --------lock-结束 threadid6--------

解决方案:

方法一:去掉program中的PushCache方法,main方法中直接调用MessageCacheBll.GetInstance().PushCache(search)

示例代码:

/// <summary>
        /// 应用程序的主入口点
        /// </summary>
        static void Main()
        {
            Log4Helper.GetInstance().Info("服务启动");
            try
            {
                ThreadPool.QueueUserWorkItem(MessageCacheBll.GetInstance().PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(MessageCacheBll.GetInstance().PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(MessageCacheBll.GetInstance().PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(MessageCacheBll.GetInstance().PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(MessageCacheBll.GetInstance().PushCache, new SearchParam() { MsgType = 3 });
                TimeSpan sleepTime = new TimeSpan(1, 0, 0); //休眠一小时
                while (true)
                {
                    Thread.Sleep(sleepTime);
                }
            }
            catch (Exception e)
            {
                Log4Helper.GetInstance().Error(e);
            }
        }

日志输出结果:

2020-01-01 11:52:47,016 服务启动

2020-01-01 11:52:47,027 --------lock-开始 threadid3--------

2020-01-01 11:52:47,508 --------lock-结束 threadid3--------

2020-01-01 11:52:47,508 --------lock-开始 threadid4--------

2020-01-01 11:52:47,852 --------lock-结束 threadid4--------

2020-01-01 11:52:47,852 --------lock-开始 threadid5--------

2020-01-01 11:52:48,038 --------lock-结束 threadid5--------

2020-01-01 11:52:48,038 --------lock-开始 threadid6--------

2020-01-01 11:52:48,292 --------lock-结束 threadid6--------

2020-01-01 11:52:48,292 --------lock-开始 threadid7--------

2020-01-01 11:52:48,413 --------lock-结束 threadid7--------

 

方法二:将MessageCacheBll中的PushCache放到program中,lock也放到program中

示例代码:

static class Program
    {
        /// <summary>
        /// 应用程序的主入口点
        /// </summary>
        static void Main()
        {
            Log4Helper.GetInstance().Info("服务启动");
            try
            {
                ThreadPool.QueueUserWorkItem(PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(PushCache, new SearchParam() { MsgType = 3 });
                ThreadPool.QueueUserWorkItem(PushCache, new SearchParam() { MsgType = 3 });
                TimeSpan sleepTime = new TimeSpan(1, 0, 0); //休眠一小时
                while (true)
                {
                    Thread.Sleep(sleepTime);
                }
            }
            catch (Exception e)
            {
                Log4Helper.GetInstance().Error(e);
            }
        }

        private static readonly object _lockThread = new object();
        /// <summary>
        /// 按照消息类型和学段跑数据
        /// </summary>
        /// <param name="search">msgType消息类型</param>
        public static void PushCache(object obj)
        {
            var search = (obj as SearchParam) ?? new SearchParam();
            try
            {
                var sqlWhere = "";
                if (search.MsgType == -1)
                {
                    sqlWhere += " and spm.type in(1,3,4,5,6,100) ";
                }
                else
                {
                    sqlWhere += string.Format(" and spm.type={0} ", search.MsgType);
                }
                List<SpMessageDto> list = new List<SpMessageDto>();
                var updateCacheStatusResult = false;//更新缓存状态结果
                //锁 获取当前线程要跑的数据
                try
                {
                    lock (_lockThread)
                    {
                        Log4Helper.GetInstance().Info(string.Format("--------lock-开始 threadid{0}--------",
                            Thread.CurrentThread.ManagedThreadId));
                        list = MessageCacheDal.GetInstance().GetNoCacheMessageList(sqlWhere);
                        if (list != null && list.Count > 0)
                        {
                            var idList = list.Select(t => t.Id).ToList();
                            updateCacheStatusResult = MessageCacheDal.GetInstance()
                                .UpdateMessageCacheStatus((int)AppEnum.CacheStatus.Caching, idList);
                        }

                        Log4Helper.GetInstance().Info(string.Format("--------lock-结束 threadid{0}--------",
                            Thread.CurrentThread.ManagedThreadId));
                    }
                }
                catch (Exception e)
                {
                    Log4Helper.GetInstance().Error(e);
                }
            }
            catch (Exception e)
            {
                Log4Helper.GetInstance().Error(string.Format("异常 msgType:{0}。", search.MsgType), e);
            }
        }

日志输出记录:

2020-01-01 11:57:35,878 服务启动

2020-01-01 11:57:35,888 --------lock-开始 threadid4--------

2020-01-01 11:57:36,586 --------lock-结束 threadid4--------

2020-01-01 11:57:36,586 --------lock-开始 threadid6--------

2020-01-01 11:57:36,789 --------lock-结束 threadid6--------

2020-01-01 11:57:36,789 --------lock-开始 threadid3--------

2020-01-01 11:57:37,186 --------lock-结束 threadid3--------

2020-01-01 11:57:37,186 --------lock-开始 threadid5--------

2020-01-01 11:57:37,279 --------lock-结束 threadid5--------

2020-01-01 11:57:37,279 --------lock-开始 threadid7--------

2020-01-01 11:57:37,394 --------lock-结束 threadid7--------

猜你喜欢

转载自www.cnblogs.com/jiangqw/p/12128497.html