C#lock问题

问题描述

情看下面的代码:publicclassMyClass{staticAutoResetEventauto=newAutoResetEvent(true);publicvoidrun1(){lock(this){Console.WriteLine("当前线程:"+Thread.CurrentThread.Name);auto.WaitOne();Console.WriteLine("{0}执行完",Thread.CurrentThread.Name);}}publicvoidsend(){auto.Set();Console.WriteLine("已经释放信号");}publicvoidrun(){run1();send();}}classProgram{staticvoidMain(string[]args){MyClassmyclass=newMyClass();for(inti=1;i<=5;i++){Threadth=newThread(myclass.run);th.Name=i.ToString();th.Start();}Console.Read();}}这段代码中,lock代码同一时间只有一个线程可以访问。线程执行run(),加入线程a首先执行run(),由于staticAutoResetEventauto=newAutoResetEvent(true);,因此auto.WaitOne();在线程1执行时,不起作用;假设线程执行后,线程b执行,那么线程b执行run(),,首先执行run()中的函数run1()和send()函数,这时线程2执行到auto.WaitOne();时,由于没有Set(),因此将等待,那么lock代码区应该不会退出,这时其他的线程执行run()时,也必须先执行run1()再执行send(),这时候由于run1()中的lock代码块被线程2占用,这时其他线程不应该无法执行,而是在等待吗?可是执行的结果,其他线程却是可以执行的,为什么呢?

解决方案

解决方案二:
引用楼主jsnanjing1的回复:

这时线程2执行到auto.WaitOne();时,由于没有Set()

第一个线程不帮他Set了么?写这么绕的代码把自己绕进去了
解决方案三:
msdn明确告诉你了,lock(this)是错误的写法,你还用
解决方案四:
弄个全局的静态变量做锁
解决方案五:
自己定义一个锁,你的用法本身就是无效的。线程已经切换,你只是让它切换后独占而已。
解决方案六:
看看C#多线程的同步和互斥
解决方案七:
classProgram{staticvoidMain(string[]args){MyClassmyclass=newMyClass();for(inti=1;i<=5;i++){Threadth=newThread(myclass.run);th.Name=i.ToString();th.Start();}Console.Read();}}publicclassMyClass{privateAutoResetEventauto=newAutoResetEvent(true);privatestaticreadonlyobject_lock_test=newobject();publicvoidrun1(){lock(_lock_test){Console.WriteLine("当前线程:"+Thread.CurrentThread.Name);auto.WaitOne();Console.WriteLine("{0}执行完",Thread.CurrentThread.Name);}}publicvoidsend(){auto.Set();Console.WriteLine("已经释放信号");}publicvoidrun(){run1();send();}}

解决方案八:
该回复于2016-06-29 12:11:06被版主删除
解决方案九:
引用6楼sgyiliya的回复:

classProgram{staticvoidMain(string[]args){MyClassmyclass=newMyClass();for(inti=1;i<=5;i++){Threadth=newThread(myclass.run);th.Name=i.ToString();th.Start();}Console.Read();}}publicclassMyClass{privateAutoResetEventauto=newAutoResetEvent(true);privatestaticreadonlyobject_lock_test=newobject();publicvoidrun1(){lock(_lock_test){Console.WriteLine("当前线程:"+Thread.CurrentThread.Name);auto.WaitOne();Console.WriteLine("{0}执行完",Thread.CurrentThread.Name);}}publicvoidsend(){auto.Set();Console.WriteLine("已经释放信号");}publicvoidrun(){run1();send();}}

这样运行结果差不多,线程是要执行方法run1和send,如果run1没有执行完,是不会执行send的。现在线程1在执行run1时,由于起初设置的privateAutoResetEventauto=newAutoResetEvent(true);,因此可以执行完run1和send。假设线程2第二个执行run,那么线程2就会在run1代码中阻塞,此时的send无法执行到,下一个线程执行时应该在run1等待,因为线程2执行时,lock代码段锁定,要等带Set。可是实际并不是这样。
解决方案十:
lock(this)不应该用应该顶一个Objectobj=newObject();....lock(obj)
解决方案十一:
同一时间只会有一个线程进入lock没有问题,但是,每次lock都会exit,因为你有send方法set
解决方案十二:
引用2楼caozhy的回复:

msdn明确告诉你了,lock(this)是错误的写法,你还用

看下他历史发帖,明显是倒分的,不知道该上哪举报
解决方案十三:
引用11楼shingoscar的回复:

Quote: 引用2楼caozhy的回复:
msdn明确告诉你了,lock(this)是错误的写法,你还用

看下他历史发帖,明显是倒分的,不知道该上哪举报

谢谢举报,和我说就可以。已经处理。
解决方案十四:
引用2楼caozhy的回复:

msdn明确告诉你了,lock(this)是错误的写法,你还用

不知道是从什么时候从哪里看到我就开始经常这样写。。。
解决方案十五:
引用13楼crystal_lz的回复:

Quote: 引用2楼caozhy的回复:
msdn明确告诉你了,lock(this)是错误的写法,你还用

不知道是从什么时候从哪里看到我就开始经常这样写。。。

https://msdn.microsoft.com/zh-cn/library/c5kehkcz(VS.80).aspx
解决方案:
引用11楼shingoscar的回复:

Quote: 引用2楼caozhy的回复:
msdn明确告诉你了,lock(this)是错误的写法,你还用

看下他历史发帖,明显是倒分的,不知道该上哪举报

倒分是什么意思?。。。
解决方案:
引用14楼caozhy的回复:

Quote: 引用13楼crystal_lz的回复:
Quote: 引用2楼caozhy的回复:
msdn明确告诉你了,lock(this)是错误的写法,你还用

不知道是从什么时候从哪里看到我就开始经常这样写。。。

https://msdn.microsoft.com/zh-cn/library/c5kehkcz(VS.80).aspx

好吧我记住了。。。网上流传的代码害人啊。。。
解决方案:
引用15楼crystal_lz的回复:

倒分是什么意思?。。。

把分结给自己小号

时间: 2024-09-12 23:27:50

C#lock问题的相关文章

实现自己的Lock对象

一直想好好学习concurrent包中的各个类的实现,然而经常看了一点就因为其他事情干扰而放下了.发现这样太不利于自己的成长了,因而最近打算潜心一件一件的完成自己想学习的东西. 对concurrent包的学习打算先从Lock的实现开始,因而自然而然的就端起了AbstractQueuedSynchronizer,然而要读懂这个类的源码并不是那么容易,因而我就开始问自己一个问题:如果自己要去实现这个一个Lock对象,应该如何实现呢? 要实现Lock对象,首先理解什么是锁?我自己从编程角度简单的理解,

x86指令集中lock前缀的意义

接上篇(https://yq.aliyun.com/articles/59019 ),对一个变量进行加法操作,可以是3条指令,也可以是1条指令.区别在于,1条指令属于原子操作,不会被打断,那是不是只要1条指令的形式,多线程之间就不需要加锁了呢?我们先试试看.(以下代码仅适用于x86平台,gcc编译器) #include <stdio.h> #include <pthread.h> int count = 0; void add(void arg) { int i; for (i =

library cache lock 的解决案例

cache|解决  下午,业务人员报告,执行任何和zzss03201281cs_no表有关的操作都会hang住,包括desc zzss03201281cs_no,也会hang在那里 第一感觉是锁了,于是,我看看锁 SQL> select * from v$lock where block=1; no rows selected SQL> SQL> select * from gv$lock where block=1; no rows selected SQL>   再看看等待事件

Library Cache Lock的解决

cache|解决 昨晚业务系统导入资料并重建索引时一个会话突然停滞不前,用TOAD一看,一直在等待Library Cache Lock.TOAD.OEM中都看不到此锁,会话每三秒启动一次,但每次都是等待这个锁.显然,这和数据字典有关,应该是一个索引的数据字典中的记录被锁住了,导致无法重建.可是杀光了其他ACTIVE的会话,问题仍然没有得到解决,看来是某一个被杀死的会话持有该锁,而会话尚未回滚完全,进程仍然吊死着.现在的问题就是找这个会话了.首先想到的文档就是Oracle9i Database R

彻底搞清楚library cache lock的成因和解决方法(一)

cache|解决 问题描述:接到应用人员的报告,说是在任何对表CSNOZ629926699966的操作都会hang,包括desc CSNOZ629926699966,例如: ora9i@cs_dc02:/ora9i > sqlplus pubuser/pubuser SQL*Plus: Release 9.2.0.4.0 - Production on Mon Jan 10 10:11:06 2005 Copyright (c) 1982, 2002, Oracle Corporation. 

接ACCESS时出现80004005 Couldnt Lock File错误的解决

access|错误|解决 适用于: Microsoft Active Server Pages Microsoft Data Access Components 1.5 Microsoft Data Access Components 2.0 Microsoft Data Access Components 2.1 Microsoft Data Access Components 2.1 SP1 Microsoft Data Access Components 2.1 SP2 Microsoft

shared pool latch/ library cache latch /lock pin介绍

latch:library cache --desc v$librarycache; latch:library cache用于保护hash bucket. library cache lock保护HANDLE. library cache pin保护library cache object--LCO. 从10G开始,library cache lock和library cache pin被MUTEX部分取代.暂时不讨论MUTEX. latch:library cache的数量: SYS@ by

ubuntu安装软件提示无法打开锁文件 /var/lib/dpkg/lock

用apt-get 安装 make提示"无法打开锁文件 /var/lib/dpkg/lock " # apt-get install vim E: 无法打开锁文件 /var/lib/dpkg/lock - open (2: 没有那个文件或目录) E: 无法对状态列表目录加锁(/var/lib/dpkg/),请查看您是否正以 root 用户运行? 出现这样的问题往往是因为无删除了这写文件!! 解决方法: 建一个空文件并复制到相应的地方: touch lock copy lock /var/

Java多线程同步问题的探究(三、Lock来了,大家都让开【1.认识重入锁】)

在上一节中,我们已经了解了Java多线程编程中常用的关键字synchronized,以及与之相关的对象锁机制.这一节中,让我们一起来认 识JDK 5中新引入的并发框架中的锁机制. 我想很多购买了<Java程序员面试宝典>之类图书的朋友一定对下面这个面试题感到非常熟悉: 问:请对比synchronized与java.util.concurrent.locks.Lock 的异同. 答案:主要相同点:Lock能完成synchronized所实现的所有功能 主要不同点:Lock有比synchroniz

C#中Monitor和Lock简介及区别

1.Monitor.Enter(object)方法是获取锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的 两个方法,当然在使用过程中为了避免获取锁之后因为异常,致锁无法释放,所以需要在try{} catch(){}之 后的finally{}结构体中释放锁(Monitor.Exit()). 2.Monitor的常用属性和方法: Enter (Object) 在指定对象上获取排他锁. Exit(Object) 释放指定对象上的排他锁. IsEntered 确 定