c#多线程lock无效

摘要:
编写Windows服务时,需要使用多线程数据。在执行方法中,锁定一段代码。日志记录后,发现它无效且不起作用。;}#Endregion//////根据消息类型和段运行数据////msgType消息类型publicvoid PushCache{varsearch=??newSearchParam();尝试{varsqlWhere=“”;如果{sqlWhere+=“andspm.typein”;//1条系统消息、3条消息、4条作业、5个年级通知、6次休假、100个年级通知发件箱使用}其他{sqlWhere+=string.Format;}ListList=newList();varupdateCacheStatusResult=false;//更新缓存状态结果//锁获取当前线程要运行的数据,请尝试{lock{Log4Helper.GetInstance().Info;list=MessageCacheDal.GetInstance().GetNoCacheMessageList;if(list!

 在写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--------

免责声明:文章转载自《c#多线程lock无效》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Spring配置-数据库连接池proxool[转]eclipse+maven+ssm框架搭建下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

Grub4dos安装和启动完全指南

1.从MBR开始。将GRUB4DOS启动代码安装到MBR后,您可以使用它将启动代码更容易地安装到MBR/启动扇区。...

Visual Studio Code 之 运行java代码

2、安装成功后,会在右键菜单中多出一个选项:更改vscode“用户设置”文件:添加java.home以及runcode显示在终端coderunner原生的配置有些问题,更改其中终端的命令:加入红色的部分3、点击RunCode,会执行相应的文件...

TCL基本语法2

TCL基本语法21、format和scan两个基本的函数,和C语言中的sprintf和scanf的作用基本相同。format将不同类型的数据压缩在字符串中,scan将字符串中的数据提取出来。setnameJacksetage100setworker[format"%sis%dyearsold"$name$age]puts$workerscan$worker"...

Oracle11g温习-第七章:redo日志

thread:线程,在单实例的环境下,thread#永远是1sequence:日志序列号。在日志切换时会递增。FIRST_CHANGE#:在当前日志中记录的首个数据块的scn。...

Maven settings.xml配置详解

让我们来谈谈设置。对于Maven,xml相当于全局配置,用于所有项目。maven2-xml中有两个设置,作为全局配置位于maven2的安装目录conf下。对于团队设置,一致的定义是关键,因此maven2/conf Xml下面的设置是团队的通用配置文件。当然,每个成员都需要特殊的用户定义设置,例如用户信息,其他设置也是如此。xml用作本地配置。默认位置为:${...

dbeaver 驱动安装

一、背景:在Windows10安装dbeaver数据库连接工具,点“测试连接”的时候出现报错如下:ErrorresolvingdependenciesMavenartifact'maven:/mysql:mysql-connector-java:RELEASE'nofound经网上查询是dbeaver驱动无法下载的问题。二、解决方法:打开“窗口”-˃“首选项...