=SMALL(IF(MOD(ROW(INDIRECT(A1&":"&A2)),2)=0,ROW(INDIRECT(A1&":"&A2))),RANDBETWEEN(1,COUNT(0/(MOD(ROW(INDIRECT(A1&":"&A2)),2)=0))))
同时按下CTRL+SHIFT+回车,输入数组公式,就可以得到结果。
不断按下F9键,可查看变化结果。
这是个有意思的问题首先,你看到的结果总是0是你自己的失误。因为你让用户输入i,并循环i次产生i个随机数放到数组里面。那么很有可能(比如我)输入了i等于10,那么实际上只会有10个随机数。而你的数组却申明成了100个元素,于是你最后打印的时候一定会打印100个值。但是后面的值全是0(因为从来没有改动过),而命令行运行的显示行数有限,所以你看到的永远是最后的0。如果你把线程B和C的打印次数设置成i次,那么你将(很有可能)看到非0的值。我想这也是zhangtuoshu 网友告诉你让你用List的原因 ,因为List是逐步增长的,所以你最后打印的时候不会打印无意义的0,而是list里面有多少元素打印多少
其次,即便你使用了上述改变方法,看到了非0的结果,你的程序仍然是不对的。它没有如你预料的实现一个生产者消费者的多线程程序。检验方式是:你在A线程的最初让它睡上1秒钟,这时候BC线程依然会运行,然后打印很多0。我想你的本意是A产生i个随机数,然后BC完全接收到这些随机数。如果A不开始,那么BC应该等待。(如果你不是这个意思,那么是我搞错了,可以无视下面的话)
问题在于,你从最开始就让ABC三个线程去竞争那两个数组资源。一旦BC竞争到资源,那么将马上打印数组的元素,并结束线程。无论A之后又生成了什么数据,BC都不会看到,因为它们已经结束了。
另外关于C#的多线程机制,本人虽然几乎没有经验。但是从文档来看,Monitor.Enter和Exit的行为和lock应该是一致的。因此我觉得这里只需要用到lock即可,甚至没有必要在lock内部调用Pulse,因为即使不调用的话,当你释放锁,别人也会去竞争锁的吧
在多说一句:if (arrayShareTwo.Length <0) 这句检查是没有必要的,也从来不会执行。你要想,什么时候一个数组的长度会小于0?永远不会,不要说你那两个数组一定会在main之前就建立完毕了,就算它们可能在线程启动之后再建立,也最多是null和非null的区别,它们的长度永远是非负的
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)