代码:
private static object lockObj = new object(); public void ProcessRequest(HttpContext context) { lock (lockObj) { context.Response.Write(GetResult()); } }
我在本地调试发现这个锁是能锁住并发的,然后都把vs2010的调试服务器搞死了(ASP.NET Development Server自动退出了,浏览器端一直是“正在等待localhost的响应“)
这个代码是别人写的,最初目的是为了防止撤销操作的重复操作。
我想问下:
1)在iis服务器下,这个代码真的会阻止并发吗?比如有100个同时来撤销操作,后面的99个人都会被迫等待第一个人吗?
2)为了防止生成重复的随机码或者某项功能被重复操作,用锁的这种方法可靠吗?
先抛开实现是否合理,但就功能上你这个lock能干嘛?多次请求还是要等着执行啊,只是在单进程中变成顺序执行而已了。
简单点实现你拉个表什么的在执行到这里时在表中打个标记,同时带上超时时间,执行的进程标识,然后一个事务性的存储过程用乐观锁处理下就可以了。同时可以让那些无法更新或插入数据的请求在这里可以明显区分开来做不同逻辑处理。
膜拜大神,还是不太会用。
@荆棘人: 。。。。之前写的都丢了。再大概写一次吧
不要lock,web应用中千万不要做lock,一则没意义,二则资源开销太大你耗不起
防止重复提交是前端的事,你最多只是配合。
耗时长需要排队的操作改为异步丢队列,前端长连接过来轮询结果即可。
@Daniel Cai: 嗯好的,学习到了很多!
我自己写了个测试代码。
private static object lockObj = new object(); public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; lock (lockObj) { Thread.Sleep(15000); context.Response.Write("Hello World"); } }
发现请求确实是被阻塞了。只会阻塞该文件bf.ashx,不会影响到default.aspx。
当work池满了,default.aspx就“堵”起了。
你需要的锁不是这里的锁。锁有很多,你这只是进程内线程间的锁。
业务操作的锁都是用数据库事务来做的.web层不做这些
嗯,受到了指导。系统是后台管理系统,用户比较少,以前是这么写的。
数据库事务用的很少,不熟练,一直不愿意主动用。
可以做一个用户级别的锁。
用户级别的锁?你是说判断登录人名字吗?用他的名字当锁?
@荆棘人: 字符串当然不是首选,最好是服务器为每一个用户维护一个锁对象。然后操作时候获取当前登录用户的锁对象,然后lock这个对象
@长蘑菇星人: 不明白啥意思。
可以看下锁的作用域,在web站点后台还是有区别的,理论上是可以加锁的
看了所有答案,自己也做测试了,还是迷惑。
1,你这种写法,是会阻塞住其他线程的。
2,如果并发不高,且站点是单点的,这种写法问题倒没没什么大问题。如果并发量大可以在数据库使用行版本来解决,如果应用做了负载均衡,要使用分布式锁,
确实如此,不过还是不太会用。
读写 Application,Cache 这些全局共享 变量要加 lock,
读写 文件IO,网络IO 这些要lock