问题描述
情看下面的代码: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的回复:
倒分是什么意思?。。。
把分结给自己小号