【发布时间】:2018-04-05 15:14:37
【问题描述】:
假设有一个多线程API,从输入队列读取请求,处理请求,然后将数据写入输出队列。
但是有一个约束:所有传入请求的结果应该按照接收到的顺序写入 O/P 队列。
示例:
请求:[r1, r2, r3]
输出应该是相同的顺序:[o1, o2, o3]
问题:如何同步线程,使输出队列中的所有数据都像输入队列一样保持顺序??
我给了面试官3个答案:
第一个答案:
假设线程 [t1, t2, t3] 处理传入请求 [r1,r2,r3]
在这种情况下我们可以加入: t2 加入 t1 t3 加入 t2 这样可以维持处理顺序。
上述解决方案的问题: 1.必须为每个请求创建新线程。 2. 线程在处理并写入输出后必须退出。
显然上述解决方案是不可行的,因为如果有一个线程池并且我们有有限数量的线程怎么办。
第二个解决方案:
当线程从输入队列中获取请求时,锁定输出队列。
线程 t1 在输出队列上获取 r1 和互斥锁。
显然 t2 和 t3 将无法处理请求 r2 和 r3。
上述解决方案的问题:
1.这里不能实现并发。
2.单个线程只能处理单个请求。
3.这里不能应用线程池的概念。
第三种解决方案:
我们可以在全局数据结构中维护请求的顺序。
线程 t1 取 r1 并在数据结构中添加优先级 p1。
数据结构:[p1]
线程 t2 取 r1 并在优先级数据结构中添加 p2
数据结构:[p1, p2]
现在假设线程 t2 完成了 r2 的处理并愿意将输出 o2 写入 O/P 队列。 t2 将检查数据结构,并会发现 p1 中的第一个元素与 t2 在优先级数据结构中输入的内容不同。所以 t2 将继续有限的等待时间并再次检查。
同时 t1 现在完成并愿意将输出 o1 写入 O/P 队列。它检查数据结构,发现第一个元素是 p1,它是由 t1 自己插入的。因此 t1 将写入输出队列并将 p1 从全局优先级数据结构中删除。
请注意:
[使用互斥锁和其他机制可以使全局优先级数据结构成为线程安全的。这里的问题不同:)]
我已经给面试官上面的答案,我认为我的第三个答案是正确的。
但面试官似乎对我的回答并不满意。
谁能给出这个问题的正确解决方案?
根据给出的答案,我想添加更多细节:
1) 主线程不负责将数据写入输出队列。每个线程都会将结果写入 O/P 队列
2)单个线程可能以连续方式处理多个请求。
例如:
线程 T1 处理请求 R1,然后线程 T2 处理请求 R2,然后线程 T1 将输出 o1 放入 O/P 队列,并从 I/P 队列中选择另一个请求 R3 进行处理。
所以现在线程 T1 处理 R3,线程 T2 正在处理 R2 请求。
3) 也可以有许多客户端向 I/P 队列写入请求。不是客户按特定顺序和优先级提出请求。
优先级是在先到先服务器的基础上设置的。
客户端 C1 在另一个客户端 C2 提出 R2 请求之前提出 R1 请求。 因此,针对 R1 请求的输出应首先写入 O/P 队列。
【问题讨论】:
-
用序列号标记每个请求,将输出与请求的序列号相关联,使用序列号作为键将输出保存在映射中,下一个序列号的任何输出都可以发出直到阻塞等待下一个序列输出。
标签: c++ multithreading process synchronization ipc