首页新闻找找看学习计划

关于IIS下网站lock静态锁无效问题

0
悬赏园豆:60 [已解决问题] 解决于 2018-10-29 17:59
public class OrderJob : IJob
{
    private static readonly object LockObj = new object();

    public void Execute(IJobExecutionContext context)
    {
        //判断是否可以获取到排它锁,如果获取不到,则跳出等待
        var canEnter = Monitor.TryEnter(LockObj);
        if (!canEnter) return;
        lock (LockObj)
        {
            Log.Debug($"{Process.GetCurrentProcess().Id}:{Thread.CurrentThread.GetHashCode()}:{this.GetType().Name} : entered:{DateTime.Now:yyyy-MM-dd HH:mm:ss ffffff}");

            Log.Debug($"{Process.GetCurrentProcess().Id}:{Thread.CurrentThread.GetHashCode()}:{this.GetType().Name} exited:{DateTime.Now:yyyy-MM-dd HH:mm:ss ffffff}");
        }
    }
}

以上代码,记录的日志表明,即使处于同一个进程ID下,这个lock完全无效,无法阻止其它线程同时进入lock区域

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.FightGroupJob.Execute
错误描述:1249476:88:FightGroupJob entered:2017-04-27 10:40:00 055398 出错方法:Execute

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.RefundJob.Execute
错误描述:1249476:89:RefundJob : entered:2017-04-27 10:40:00 056375 出错方法:Execute

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.RefundJob.Execute
错误描述:1249476:69:RefundJob : entered:2017-04-27 10:40:00 058328 出错方法:Execute

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.FightGroupJob.Execute
错误描述:1249476:35:FightGroupJob entered:2017-04-27 10:40:00 059305 出错方法:Execute

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.FightGroupJob.Execute
错误描述:1249476:149:FightGroupJob entered:2017-04-27 10:40:00 060281 出错方法:Execute

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.RefundJob.Execute
错误描述:1249476:148:RefundJob : entered:2017-04-27 10:40:00 061258 出错方法:Execute

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.FightGroupJob.Execute
错误描述:1249476:6:FightGroupJob entered:2017-04-27 10:40:00 063211 出错方法:Execute

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.RefundJob.Execute
错误描述:1249476:7:RefundJob : entered:2017-04-27 10:40:00 067118 出错方法:Execute

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.FightGroupJob.Execute
错误描述:1249476:149:FightGroupJob entered:2017-04-27 10:40:00 091533 出错方法:Execute

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.FightGroupJob.Execute
错误描述:1249476:88:FightGroupJob entered:2017-04-27 10:40:00 123760 出错方法:Execute

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.FightGroupJob.Execute
错误描述:1249476:35:FightGroupJob entered:2017-04-27 10:40:00 128643 出错方法:Execute

记录时间:2017-04-27 10:40:00 日志级别:DEBUG 出错路径:Himall.Service.Job.FightGroupJob.Execute
错误描述:1249476:6:FightGroupJob entered:2017-04-27 10:40:00 147199 出错方法:Execute

记录时间:2017-04-27 10:40:01 日志级别:DEBUG 出错路径:Himall.Service.Job.RefundJob.Execute
错误描述:1249476:89:RefundJob exited:2017-04-27 10:40:01 099384 出错方法:Execute

记录时间:2017-04-27 10:40:01 日志级别:DEBUG 出错路径:Himall.Service.Job.RefundJob.Execute
错误描述:1249476:69:RefundJob exited:2017-04-27 10:40:01 123799 出错方法:Execute

记录时间:2017-04-27 10:40:01 日志级别:DEBUG 出错路径:Himall.Service.Job.RefundJob.Execute
错误描述:1249476:148:RefundJob exited:2017-04-27 10:40:01 127705 出错方法:Execute

记录时间:2017-04-27 10:40:01 日志级别:DEBUG 出错路径:Himall.Service.Job.RefundJob.Execute
错误描述:1249476:7:RefundJob exited:2017-04-27 10:40:01 406036 出错方法:Execute

心雨纷扬的主页 心雨纷扬 | 菜鸟二级 | 园豆:220
提问于:2017-04-27 11:51
< >
分享
最佳答案
0

FightGroupJob?RefundJob?这些呢?

其次tryEnter如果返回true后已经进到临界区了,没必要再次lock。

但单就你给出的这个代码而言,如果确认在同一进程下是不会出现问题的。

收获园豆:60
Daniel Cai | 专家六级 |园豆:10374 | 2017-04-27 13:40

都是类似的代码~再次LOCK不会影响,但是实际上就目前而言,进程ID一直,线程ID不一致,但是实际运行的结果就是不是预期的。

心雨纷扬 | 园豆:220 (菜鸟二级) | 2017-04-27 13:51

我追加lock的原因是我希望锁住这部分代码,其它同时进入的线程不要等待锁,所以有之前的判断

心雨纷扬 | 园豆:220 (菜鸟二级) | 2017-04-27 13:54

@心雨纷扬: 不要怀疑这个lock会出问题,如果这种玩意能出问题早玩完了。

建议还是检查代码

Daniel Cai | 园豆:10374 (专家六级) | 2017-04-27 13:59

@Daniel Cai: 我想问的就是这个代码会出什么问题???我目前就是不知道这样的代码怎么会出问题。lock目前无效啊,日志也有。证明多个线程同时进入了lock区域~~~~~~完全摸不着头脑,所以才来提问。。。。

 

虽然我贴出的代码是orderjob的,其实所有job的形式都是一样的。但是最终这个一样会同时多次进入lock区域

心雨纷扬 | 园豆:220 (菜鸟二级) | 2017-04-27 14:03

@心雨纷扬: 如果你一直担心这个代码中未锁住的问题的话,你可以把场景最小化,比如在linqpad或者控制台写个demo,就你上面那个代码你拿多个线程来压下。(不过我可以先告诉你就你前面贴的代码是不会出现任何未lock住的问题,前提是单进程)

Daniel Cai | 园豆:10374 (专家六级) | 2017-04-27 15:44

@心雨纷扬: ps下,单进程一个appdomain下。

Daniel Cai | 园豆:10374 (专家六级) | 2017-04-27 16:35

@Daniel Cai: 我刚才已经找到了appdomain这个原因了,正在寻找解决方案

心雨纷扬 | 园豆:220 (菜鸟二级) | 2017-04-27 16:47

@心雨纷扬: 这种场景下不建议再用进程内的锁了。跨appdomain的lock可以做,但感觉比较蛋疼。

这块建议是做一步到位的分布式锁。要么你就上命名的mutex

Daniel Cai | 园豆:10374 (专家六级) | 2017-04-27 16:54
其他回答(4)
0

Log.Debug 你应该在这里加锁,你在一个基类里加个锁 有何意义呢?

James.Ying | 园豆:1472 (小虾三级) | 2017-04-28 17:31

哪里有基类???这个是定时任务,根据输出日志,这个会多个线程同时进入这个job。然后造成一个数据被多次结算

支持(0) 反对(0) 心雨纷扬 | 园豆:220 (菜鸟二级) | 2017-05-03 18:02
0

如果从代码来看,应该会被锁住的,只是我想问,你为什么认为一定没锁住呢?因为不能获取锁的线程因为canEnter为false的原因已经返回了,而更晚一些执行的线程能获取到锁就执行了log,这个很合理,不能说明锁失效了。

wyman25 | 园豆:14 (初学一级) | 2017-05-03 16:29

我的锁是锁了全程啊,因为被多线程差不多同时执行,导致数据的判断字段尚未保存,最终导致结算的数据会出现重复。

 

支持(0) 反对(0) 心雨纷扬 | 园豆:220 (菜鸟二级) | 2017-05-03 18:04
0

我怎么看。都不觉得是LOCK无效,CPU速度是非常快的,好的CPU你这代码一秒内执行个百万次循环都可以。你在lock里面加上thread.sleep(1000);测试一下。看是不是一秒一条日志。

盟怀部孩 | 园豆:878 (小虾三级) | 2017-05-11 14:10
0

最终发现是形成了多个appdomain了,无法直接使用静态变量锁,产生多个appdomain的原因未知。
考虑更换分布式锁

心雨纷扬 | 园豆:220 (菜鸟二级) | 2018-10-29 17:11
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册