ios - 我们如何在swift中使用协议(protocol)实现并发线程?

标签 ios swift multithreading protocols

<分区>

我在面试 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 类中实现上述协议(protocol)。我试过但找不到解决方案。请帮我。提前致谢。

最佳答案

之前我建议使用目标队列,但更好的是,创建一个主并发队列,然后为命名队列创建串行队列,然后通过该主并发队列调度所有内容。与目标队列方法不同,这将遵循分配给命名队列的任务和分配给未命名队列的任务的调度。

通过该实现,这是一个示例(Instruments“兴趣点”配置文件),其中我为名为“fred”和“ginger”的队列添加了任务,还有一个被添加到未命名的队列中,然后我添加了一个屏障任务,然后向上述每个队列添加另外两个任务。

enter image description here

如您所见,它尊重命名队列的串行性质,未命名队列是并发的,所有这些队列彼此并发,但屏障是跨越所有队列的屏障。

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 数组的访问,以确保此类的线程安全。

关于ios - 我们如何在swift中使用协议(protocol)实现并发线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45627542/

相关文章:

ios - touchesEnded 在设备改变方向后没有被调用

iOS - 友好的 NSDate 格式

ios - Swift 获取 Facebook AccessToken

ios - 迭代对象 Swift - 数组超出索引 - TableView 中的 AlamofireObjectMapper

C++多线程安全局部变量?

python - Python如何一次上传多个文件到云文件?

ios - iOS - Xcode 中的文件所有者和第一响应者是什么?

iOS( swift ): How to resize the height of an UIWebView when keyboard is/not in use

java - Thread.sleep 在循环中调用 - 在这种情况下如何防止它(通过重构)?

ios - 同时使用 swift 和 obj c