这是一个面试问题,被问到并希望找到一个有效的解决方案。
问题
考虑如图所示的四条道路的交叉点。每条道路都被定义为有一个方向。您将如何解决这个问题,以改善交通状况并避免死锁。
- 交叉点分为四个象限[以黄色显示]。
- 汽车从四个方向[0,1,2,3]随机进入交叉路口,
- 在交叉路口每辆车可以单次移动。三种可能的行动是
- 向左走
- 直走
- 向右走
例如:
如果汽车从方向 2 驶入并想要左转。它应该通过
象限 2、象限 1 以及最后的象限 0

半完整解决方案
每个用黄色标记的象限都有一个与之关联的信号量。
我想象的是一个两阶段协议,其中每辆车都会
- 获得它将通过的象限列表,
- 锁定从最后一个象限开始的每个象限
- 在上面的示例中,来自方向 2 的汽车将锁定象限 0、象限 1,然后锁定象限 2 >.
- 通过交叉路口
- 释放获得的锁。
- 锁以相同的顺序释放。 象限 0、象限 1 和象限 2
但是,上述解决方案并不是最优的,因为它会导致死锁。 em>
我的问题是
- 还有什么其他/更好的方法可以实现这一点?
- 我可以使用 C 中的信号量来实现吗?
- 如果不是,我应该考虑什么同步方法?
更新
- 我想要一个解决方案,允许多辆车进入交叉路口,并且仍然避免死锁和碰撞。在整个交叉路口上有一个锁将不够优化。
This is a interview Question which was asked and wanted to find an efficient solution.
Problem
Consider a intersection of four roads as shown in the diagram. Each road is defined to have a direction. How would you solve the problem so as to improve the traffic condition and avoid deadlocks.
- the intersection is divided into four quadrants [shown in yellow].
- Cars enter the intersection at random from the four direction [0,1,2,3]
- At the intersection each car can make a single move. the three possible moves are
- Go left
- Go straight
- Go right
e.g :
if a car enters from direction 2 and wants to take a left turn. it should pass through
quandrant 2 , quandrant 1 and finally quandrant 0

Semi complete solution
Each quadrant marked in yellow has a semaphore associated with it.
What I imagined was a 2 phase protocol wherein each car would
- get list of quadrants it will pass through
- lock each of the quadrants starting from the last quadrant
- In the above example the car from direction 2 would lock quadrant 0, quadrant 1 and then quadrant 2.
- Move through the intersection
- Release the locks acquired.
- The locks are released in the same order. quadrant 0, quandrant 1 and the quandrant 2
However the above solution is less than optimal as it results in a deadlock.
My Question is
- What other /better way can this be achieved?
- Can I implement this using a semaphore in C?
- If not what synchronization method should I be looking at?
Updates
- I want a solution which allows multiple cars can enter the intersection and still avoid deadlock as well as collision.Having a single lock on the entire intersection would be less than optimized.
发布评论
评论(4)
您的解决方案(如步骤 2 中建议的那样)无法避免死锁。
考虑一下当来自四条街道的车辆想要向左转时的情况。然后所有的汽车开始锁定不同的方向:
从方向 0 开始,它锁定方向 2。
从方向 1 开始,它锁定象限 3。
从方向 2 开始,它锁定象限 0。
从方向 3 开始,它锁定象限 1。
-- 死锁 --
您可以通过四个方向共享互斥体来避免死锁。
Your solution (as suggested in step 2) does not avoid deadlock.
Consider the case when from the four streets there are cars wanting to turn to their left. Then all the cars start locking different cuadrants:
from direction 0, it locks cuadrant 2.
from direction 1, it locks cuadrant 3.
from direction 2, it locks cuadrant 0.
from direction 3, it locks cuadrant 1.
-- deadlock --
You could avoid the deadlock by having a mutex shared by the four directions.
我假设您的“最后象限”锁定顺序是它在穿过交叉点时看到的最后一个?
我认为您可以更改算法以始终按数字顺序锁定象限 - 如果有任何已锁定,则解锁并重试。汽车必须先锁定其完整路径,然后才能驶过十字路口并解锁。例如,如果一辆汽车想要从路径 1 行驶到 2,它将首先锁定象限 0,然后锁定象限 3。如果它想从路径 3 行驶到 1,那么它将首先锁定象限 2,然后锁定象限 3。
我认为这解决了死锁问题,因为每个线程都以相同的顺序锁定。当某人锁定 3 0 1 和某人锁定 1 2 3 时,就会发生死锁。
因此,完整的任务列表将是:
`pthread_mutex_trylock()
为每个象限加一个锁。正如您所提到的,它不能做的是锁定其第一个象限,进入该象限,然后尝试锁定路径中的下一个象限。在这种情况下,这会导致僵局或僵局。
I assume your "last quadrant" locking order is last that it sees as it moves through the intersection?
I think you can change your algorithm to always lock the quadrants in numerical order -- unlocking if any is already locked and retry. The car would have to lock its complete path before driving through the intersection and unlocking. For example, if a car wanted to go from path 1 to 2 it would lock first quadrant 0 and then 3. If it wanted to go from path 3 to 1 then it would lock 2 first and 3 next.
I think that solves the deadlock issue because each thread is locking in the same order. Using your Deadlock happens when someone locks 3 0 1 and someone while someone is locking 1 2 3.
So the complete task list would be:
`pthread_mutex_trylock()
with a lock for each quadrant.As you mention, what it can't do is lock it's first quadrant, enter that quadrant and then try to lock the next one in the path. That would lead to deadlock or gridlock in this case.
我能够使用以下逻辑在 C 中实现解决方案(实际实现对每个象限使用信号量)。
我在问题中提到的解决方案部分正确,但是由于锁定的问题,我遇到了死锁。
我能够通过为锁分配优先级来解决这个问题。
通过首先锁定最高优先级的锁来获得锁。
以下是每辆车使用的伪代码算法:
假设:
*其中Lock_x是象限x 算法
每辆车都会获得它将经过的象限列表
从优先级最高的象限开始锁定每个象限。
例如:在上面的示例中,来自方向 2 的车辆左转将锁定象限 2、象限 0,然后锁定象限 1 .
穿过十字路口
释放获取的锁。
例如:在上面的示例中,锁以相同的顺序释放。 象限 2、象限 1 和象限 0
I was able to implement a solution in C using the following logic (The actual implementation used semaphores for each of the quadrant).
The solution I mentioned in the question was partially correct however I was experiencing deadlock due to the matter in which locks were made.
I was able to solve the issue by assigning priority to the locks.
The locks are gained by locking highest priority lock first.
Following is a pseudo-code algorithm used by each of the car:
Assumptions:
Algorithm
Each car gets list of quadrants it will pass through
Lock each of the quadrants starting from the quadrant with highest priority.
e.g: In the above example the car from direction 2 taking a left turn would lock quadrant 2, quadrant 0 and then quadrant 1.
Move through the intersection
Release the locks acquired.
e.g: In the above example the locks are released in the same order. quadrant 2, quandrant 1 and the quandrant 0
您实际上可能不需要信号量来实现解决方案。
问题并不是真正的资源控制(不需要锁定象限)
是关于资源调度的。
让我们假设运动/时间以离散的步骤发生
,以知道何时开始移动您的汽车,您必须预测象限是否会在您将来需要时使用。为此,当每辆车进入十字路口时,它应该描述它的意图..使用步骤队列..示例:
让我们有一个队列,每个象限有 1 行,
当汽车 1 来自底部时(2)他将使用(象限:2 1 0) 所以他保留 如果 2号
车在刻度 2 上从右侧出现并想要前进(Q:1 0),
我们就会发生碰撞,因此每辆车只有在它需要的所有象限都为空时才尝试标记其意图。如果没有,它会将意图滑动 1 帧并重试。在这种情况下,
如果没有发生冲突,如果汽车 3 在时间帧 2 从顶部到达,则汽车 2 的时间表将是,可以尽快安排运动(0) 并且想要走到底部(Q:0 3)他可以立即开始。因为当他需要使用它时,它作为意图使用的象限不会被占用,
这是一般方法..具体实施时会有变化..
如果您有线程(每辆车一个),您可能需要同步它们对队列的访问。但这只是同步数据访问而不是交叉路口逻辑
,并且如果运动步骤不是离散的单位,队列帧必须代表 X 秒的动画。
You may actually not need semaphores to implement a solution..
the problem is not really about resource control (not need to lock quadrants)
is about resource scheduling..
lets assume that motion/time occurs in discrete steps
to know when to start moving your car you have to predict if the quadrant will be in use or not when you will need it in the future.. for that, as each car comes into the intersection it should describe its intent.. using a queue of steps.. example:
lets have a queue with 1 row for each quadrant
when car 1 comes from the bottom(2) he will use (Quadrants: 2 1 0) so he reserves the quadrants
if car number 2 comes from the right on tick 2 and wants to go forward (Q: 1 0)
we have a crash, so each car will have try to mark is intention only if all the quadrants that it needs are empty.. if not it will slide the intention by 1 frame and try again.. in this case the schedule of the car 2 would be
if no conflict occurs the motion can be scheduled as soon as possible, if car 3 comes at time frame 2 from top(0) and wants to go bottom (Q:0 3) he can start immediately. because none of the quadrants that it as intention of using, will be occupied when he will have the need to use it
this is the general method.. for specific implementation there will be variations..
if you to have threads (one for each car) you may need to synchronize their access to the queue.. but that is only to synchronize data access not the intersection logic
and if the motion steps are not discrete units, a queue frame will have to represent X seconds of animation..