     public typealias ImageStoreCompletionHandler = ((UIImage?, ImageStoreError?) -> Void)
 
     private(set) public static var shared: ImageStore = ImageStore(ImageStoreConfig())
+    private let ioQueue = DispatchQueue(label: "ImageStore_Serial_Queue")
 
     public class func reset(config: ImageStoreConfig = ImageStoreConfig()) {
         shared = ImageStore(config)

        guard let completions: [ImageStoreCompletionHandler] = completionsByURLString[url.absoluteString] else {
            return
        }
        if let _ = downloadTaskByURLString[url.absoluteString] {
            downloadTaskByURLString.removeValue(forKey: url.absoluteString)
        }
        DispatchQueue.main.async { [weak self] in
            completions.forEach { $0(nil, .taskError(error)) }

        }

        let task: URLSessionDownloadTask
        if let _task = getDownloadTask(for: url) {
            task = _task
            task.resume()
        } else {
            task = session.downloadTask(with: url)
            task.resume()
            setDownloadTask(task, for: url)
        }

        return task
    }

    public func suspendIfResuming(url: URL) {
        getDownloadTask(for: url)?.suspend()
    }

    public func cancel(url: URL) {

        if let task = getDownloadTask(for: url) {
            task.cancel()
            removeDownloadTask(for: url)
        }
    }

    private func getDownloadTask(for url: URL) -> URLSessionDownloadTask? {
        return ioQueue.sync { downloadTaskByURLString[url.absoluteString] }
    }

    private func removeDownloadTask(for url: URL) {
        _ = ioQueue.sync {
            downloadTaskByURLString.removeValue(forKey: url.absoluteString)
        }
    }

    private func setDownloadTask(_ task: URLSessionDownloadTask, for url: URL) {
        _ = ioQueue.sync {
            downloadTaskByURLString[url.absoluteString] = task
        }
    }
}

extension ImageStore: URLSessionDownloadDelegate {
