在iOS开发者角色的采访中我被问到这个问题。
// Please design a read-write task queue where you can tag the reader task with label,
// where the the task with the same label should be executed sequentially, and the
// tasks with different labels could be executed concurrently. However, the writer
// would get the exclusive access where no concurrent task would happen at the
// same time with the writer task
// For example:
protocol ConcurrentQueueWithSerialization {
// Submits a labeled task.
// All tasks with the same label will be serialized.
// Tasks with different labels will run concurrently.
// Use this method to submit a "read" operation from a particular reader.
func async(with label: String, task: @escaping () -> Void)
// Submits a task that will run concurrently with all other tasks regardless of their labels.
func async(task: @escaping () -> Void)
// Submits a labeled and delayed task.
func asyncAfter(deadline: DispatchTime, with label: String, task: @escaping () -> Void)
// Submits an unlabeled and delayed task.
func asyncAfter(deadline: DispatchTime, task: @escaping () -> Void)
// Submits a barrier task. Only one barrier task is allowed to run at a time.
// Works as a critical section for the queue.
// Use this method to submit a writer task.
func asyncBarrier(task: @escaping () -> Void)
}
class MyDispatchQueue: ConcurrentQueueWithSerialization {
//TODO: write your implementation
}
采访者让我在MyDispatchQueue类中实现上述协议。我试过但找不到解决办法。请帮我。提前谢谢。
答案 0 :(得分:6)
以前我建议使用目标队列,但更好的是,创建主并发队列,然后为命名队列创建串行队列,然后通过该主并发队列调度所有内容。与目标队列方法不同,这将使用调度到未命名队列的任务调度分派到命名队列的任务。
通过该实现,这里是一个示例(仪器“兴趣点”配置文件),其中我为名为“fred”和“ginger”的队列添加了任务,还添加了一个添加到未命名队列的任务,然后我添加了屏障任务,然后向上述每个队列添加两个任务。
正如您所看到的,它尊重命名队列的串行性质,未命名的队列是并发的,并且所有这些队列相互并发,但屏障是所有队列的障碍。
class MyDispatchQueue: ConcurrentQueueWithSerialization {
private var namedQueues = [String: DispatchQueue]()
private var queue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".target", attributes: .concurrent)
private let lock = NSLock()
private func queue(with label: String) -> DispatchQueue {
lock.lock()
defer { lock.unlock() }
if let queue = namedQueues[label] { return queue }
let queue = DispatchQueue(label: Bundle.main.bundleIdentifier! + "." + label)
namedQueues[label] = queue
return queue
}
func async(with label: String, task: @escaping () -> Void) {
queue.async {
self.queue(with: label).sync(execute: task)
}
}
func async(task: @escaping () -> Void) {
queue.async(execute: task)
}
func asyncAfter(deadline: DispatchTime, with label: String, task: @escaping () -> Void) {
queue.asyncAfter(deadline: deadline) {
self.queue(with: label).sync(execute: task)
}
}
func asyncAfter(deadline: DispatchTime, task: @escaping () -> Void) {
queue.asyncAfter(deadline: deadline, execute: task)
}
func asyncBarrier(task: @escaping () -> Void) {
queue.async(flags: .barrier, execute: task)
}
}
注意,我还同步访问namedQueues
数组,以确保此类的线程安全。