这是一个面试问题,被问到并希望找到一个有效的解决方案。
考虑如图所示的四条道路的交叉点。每条道路都被定义为有方向。您将如何解决问题,以便改善交通状况并避免死锁。
例如:
如果汽车从方向2进入并想要向左转弯。它应该通过 quandrant 2 , quandrant 1 ,最后 quandrant 0
以黄色标记的每个象限都有一个与之关联的信号量。 我想象的是一个2阶段协议,其中每辆车都将
但是上述解决方案并不是最优的,因为它会导致死锁。
答案 0 :(得分:1)
您的解决方案(如步骤2中所示)不会避免死锁。
考虑从四条街道上有车想要转向左侧的情况。然后所有的汽车开始锁定不同的cuadrants:
从方向0开始,锁定了cuadrant 2。 从方向1,它锁定cuadrant 3。 从方向2,它锁定cuadrant 0。 从方向3开始,锁定了cuadrant 1。 - 死锁 -
您可以通过四个方向共享一个互斥锁来避免死锁。
答案 1 :(得分:1)
我能够使用以下逻辑在C中实现解决方案(实际实现使用每个象限的信号量)。
我在问题中提到的解决方案部分正确但是由于锁定的问题我遇到了死锁。 我能够通过为锁分配优先级来解决问题。 通过首先锁定最高优先级锁来获得锁。 以下是每个汽车使用的伪代码算法:
<强>假设:强>
优先级(Lock_0)&lt;优先级(Lock_1)&lt;优先级(Lock_2)&lt;优先级(Lock_3)强>
*其中Lock_x是Quadrant x的锁定
<强>算法强>
从具有最高优先级的象限开始锁定每个象限。
例如:在上面的例子中,方向2左转的车将锁定象限2 ,象限0 然后象限1
穿过十字路口
释放获得的锁。
例如:在上面的示例中,锁以相同的顺序释放。 象限2 , quandrant 1 和 quandrant 0
答案 2 :(得分:0)
我假设你的“最后一个象限”锁定顺序是它在交叉点移动时看到的最后一个?
我认为您可以将算法更改为始终按数字顺序锁定象限 - 如果已锁定并重试则解锁。在开车穿过十字路口并解锁之前,汽车必须锁定其完整路径。例如,如果汽车想要从路径1转到2,它将锁定第一个象限0然后3.如果它想要从路径3转到1,那么它将首先锁定2,然后锁定3个。
我认为这解决了死锁问题,因为每个线程都以相同的顺序锁定。当某人锁定3 0 1时会发生使用死锁,而当有人锁定1 2 3时会发生这种情况。
所以完整的任务列表将是:
`pthread_mutex_trylock()
使用每个象限的锁。正如您所提到的,它不能做的是锁定它的第一象限,进入该象限然后尝试锁定路径中的下一个象限。在这种情况下,这会导致死锁或僵局。
答案 3 :(得分:0)
您实际上可能不需要信号量来实现解决方案.. 问题不在于资源控制(不需要锁定象限) 是关于资源调度..
让我们假设运动/时间以不连续的步骤发生
要知道什么时候开始移动你的车,你必须预测象限是否会在将来使用时...因为每辆车进入交叉路口时应该描述它的意图。使用一系列步骤..例如:
让每个象限有一行排队
T 1 2 3 4 5 6 7 8 9
0|
1|
2|
3|
当汽车1来自底部(2)时,他将使用(象限:2 1 0),因此他保留了象限
T 1 2 3 4 5 6 7 8 9
0| 1
1| 1
2|1
3|
如果车号2来自刻度线2的右侧并且想要前进(Q:1 0)
T 1 2 3 4 5 6 7 8 9
0| 2*1
1| 2*1
2|1
3|
我们发生了撞车事故,所以每辆车只有在需要的所有象限都是空的时候才会尝试标记。如果没有,它会将意图滑动1帧再试一次..在这种情况下,时间表汽车2将是
T 1 2 3 4 5 6 7 8 9
0| 1 2
1| 1 2
2|1
3|
如果没有发生冲突,可以尽快安排动作,如果车3从顶部(0)到达第2帧并且想要到达底部(Q:0 3),他可以立即开始。因为没有任何意图使用的象限,当他需要使用它时会被占用
T 1 2 3 4 5 6 7 8 9
0| 3 1 2
1| 1 2
2|1
3| 3
这是一般方法..对于具体实施,会有变化.. 如果您有线程(每个车一个),您可能需要同步他们对队列的访问权限..但这只是为了同步数据访问而不是交叉逻辑
如果运动步骤不是离散单位,则队列帧必须表示动画的X秒..