你为什莫这莫你牛
你牛
【相关推荐】
./main-one-cv-while -p 1 -c 2 -m 1 -C 0,0,0,3:0,0,0,3 -P 1 -l 2 -v -t
即使不配置睡眠字符串,也可能出现如下情况:
生产者生产后,缓冲区满了,唤醒了两个正在睡眠的消费者中的一个,然后进入睡眠(Mutex_lock)
消费者消费后,唤醒另一个消费者,进入睡眠(Mutex_lock),
新的消费者线程被唤醒,发现缓冲区为空,进入睡眠(Cond_wait),此时三个线程都进入睡眠
无法配置睡眠字符串,使得代码运行必定出现问题,取决与操作系统的线程调度
我尝试通过休眠字符干预程序的线程调度,想法是这样的,模拟课本引发问题的顺序:
生产者线程先运行,在p0处强制睡眠,让消费者先执行。让两个消费者都一直运行到c3处后强行睡眠,使得生产者可以在p5唤醒一个消费者后继续执行,而不是切换到消费者线程。生产者一直运行直到运行到第二次p3。然后c1运行,消费,消费完后唤醒c2,c2起来消费,发现为空。睡眠。这时候3个对象都进入睡眠。
但在实践中发现是这个样子的:
消费者运行到c2后就不再运行了,无论怎么配置睡眠因子,都不能使得一个消费者一口气执行完c0~c3。无论如何都会在c2处穿插运行一个生产者。
而且有一点非常奇怪就是红色方框下面那个c3,它执行完后立刻就变c4了。而代码逻辑是:
c3无论如何都得经过一个c2才能到c4。
所以得到两个问题使得我怀疑程序的正确性:
但我认为我的配置是正确的,也就是:
./main-one-cv-while -p 1 -c 2 -m 1 -C 0,0,0,3:0,0,0,3 -P 1 -l 2 -v -t
只是程序有问题(我有较大把握认为程序有问题),导致我运行不出想要的结果
后来经过讨论,发现课本的方案确实不好实现,跳出课本的限制。想另一种方案。
经过与同学讨论,得到了一个可以让所有线程都休眠的配置方案:
./main-one-cv-while -p 1 -c 2 -m 1 -P 0,0,0,0,0,0,1 -l 2 -v -t
最后会卡住,达到效果。其原理和课本的不同。
课本是让生产者和消费者1睡,消费者2起导致异常。具体顺序为:生产者睡->消费者1"消费完”"睡之前"唤醒消费者2(按照逻辑它应该唤醒生产者才不会错)。这里对调度干预非常严格,严格在"消费完”,“睡之前”这个两个动作必须是原子操作。可以看到:
c6(消费完)之后要马上执行c1c2c3(睡之前),这个要求是没办法确定的。这个程序的调度算法并没有让c6(消费完)执行后马上执行c1(睡之前)的机制。因此课本的方案无法复现。
同学这个方案能成功的原理是让生产者和消费者1死,消费者1死之前唤醒消费者2。此时只有消费者2,但消费者2的动作是:睡。它一旦睡了,由于生产者和消费者已经死了,不会有人再叫醒2了,2会一直睡下去。
这里,第4行,生产者生产完一个结束位后线程死亡。消费者1消费完这个结束位后线程死亡,死之前还叫醒了消费者2。