基于多线程算法的交叉口交叉仿真

时间:2012-02-22 22:51:12

标签: multithreading algorithm synchronization deadlock semaphore

这是一个面试问题,被问到并希望找到一个有效的解决方案。

问题

考虑如图所示的四条道路的交叉点。每条道路都被定义为有方向。您将如何解决问题,以便改善交通状况避免死锁

  1. 交叉路口分为四个象限[以黄色显示]。
  2. 汽车从四个方向[0,1,2,3]
  3. 随机进入交叉路口
  4. 在十字路口,每辆车都可以一举一动。三个可能的举措是
    1. 左转
    2. 直接
    3. 向右走
  5. 例如:

      

    如果汽车从方向2进入并想要向左转弯。它应该通过    quandrant 2 quandrant 1 ,最后 quandrant 0

    enter image description here

    半完全解决方案

    以黄色标记的每个象限都有一个与之关联的信号量。 我想象的是一个2阶段协议,其中每辆车都将

    1. 获取将通过的象限列表
    2. 从最后一个象限开始锁定每个象限
      1. 在上面的例子中,来自方向2 的汽车将锁定象限0 象限1 然后象限2
    3. 穿过十字路口
    4. 释放获得的锁。
      1. 锁以相同的顺序释放。 象限0 quandrant 1 quandrant 2
    5. 但是上述解决方案并不是最优的,因为它会导致死锁。

      我的问题是

      1. 还有什么其他/更好的方法可以实现?
      2. 我可以在C中使用信号量实现吗?
        1. 如果不是我应该查看哪种同步方法?
      3. 更新

        1. 我想要一个允许多辆汽车进入交叉路口的解决方案,同时仍然可以避免死锁和碰撞。整个交叉路口的单一锁定将不会优化。

4 个答案:

答案 0 :(得分:1)

您的解决方案(如步骤2中所示)不会避免死锁。

考虑从四条街道上有车想要转向左侧的情况。然后所有的汽车开始锁定不同的cuadrants:

从方向0开始,锁定了cuadrant 2。 从方向1,它锁定cuadrant 3。 从方向2,它锁定cuadrant 0。 从方向3开始,锁定了cuadrant 1。 - 死锁 -

您可以通过四个方向共享一个互斥锁来避免死锁。

答案 1 :(得分:1)

我能够使用以下逻辑在C中实现解决方案(实际实现使用每个象限的信号量)。

我在问题中提到的解决方案部分正确但是由于锁定的问题我遇到了死锁。 我能够通过为锁分配优先级来解决问题。 通过首先锁定最高优先级锁来获得锁。 以下是每个汽车使用的伪代码算法:

<强>假设:

  1. 每个象限都有一个与之关联的锁。
  2. 每个锁具有相关的优先级。优先事项如下
  3.   

    优先级(Lock_0)&lt;优先级(Lock_1)&lt;优先级(Lock_2)&lt;优先级(Lock_3)
         *其中Lock_x是Quadrant x的锁定

    <强>算法

    1. 每辆车都会获得它将通过的象限列表
    2. 从具有最高优先级的象限开始锁定每个象限。

      例如:在上面的例子中,方向2左转的车将锁定象限2 象限0 然后象限1

    3. 穿过十字路口

    4. 释放获得的锁。

      例如:在上面的示例中,锁以相同的顺序释放。 象限2 quandrant 1 quandrant 0

答案 2 :(得分:0)

我假设你的“最后一个象限”锁定顺序是它在交叉点移动时看到的最后一个?

我认为您可以将算法更改为始终按数字顺序锁定象限 - 如果已锁定并重试则解锁。在开车穿过十字路口并解锁之前,汽车必须锁定其完整路径。例如,如果汽车想要从路径1转到2,它将锁定第一个象限0然后3.如果它想要从路径3转到1,那么它将首先锁定2,然后锁定3个。

我认为这解决了死锁问题,因为每个线程都以相同的顺序锁定。当某人锁定3 0 1时会发生使用死锁,而当有人锁定1 2 3时会发生这种情况。

所以完整的任务列表将是:

  1. 它尝试以象限数字顺序(0,1,2,3)锁定其路径。如果这是C,那么我将`pthread_mutex_trylock()使用每个象限的锁。
  2. 如果发现一个象限被锁定,它将解锁它锁定的象限,睡眠一段随机时间,然后重新开始。
  3. 如果它锁定了它的完整路径,那么它就可以遍历路径。
  4. 一旦它通过一个象限,它可以安全地解锁它。在解锁之前,它不必等到另一边出去。
  5. 正如您所提到的,它不能做的是锁定它的第一象限,进入该象限然后尝试锁定路径中的下一个象限。在这种情况下,这会导致死锁或僵局。

答案 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秒..