You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止Swift函数同时多次执行?确保串行完成一个调用再执行下一个

保证日志操作串行执行的几种实用方案

你的write函数可能被多线程同时调用,要确保前一次的文件追加和日志发送完成后再执行下一次,下面是几种靠谱的实现方式:

1. 串行DispatchQueue(最常用)

在你的类里定义一个串行队列,把所有日志操作都丢到这个队列里执行——串行队列的特性就是任务会按顺序一个接一个跑,完全不会并行。

代码实现:

// 在类内部定义串行队列
private let serialLogQueue = DispatchQueue(label: "com.yourapp.log.serial")

func write(_ text: String) {
    // 把操作异步提交到串行队列
    serialLogQueue.async { [weak self] in
        guard let self = self else { return }
        // 这里的代码会严格按调用顺序执行
        text.appendLineToURL(fileURL: self.path)
        self.sendLog(text)
    }
}

为什么用async?因为这样不会阻塞调用write的线程(比如主线程),避免UI卡顿。如果你需要等待当前日志操作完成再做后续动作,也可以换成sync,但一般异步更实用。

2. DispatchSemaphore(信号量互斥)

用信号量来做互斥控制,相当于给write加了一把"锁",同一时间只有一个线程能执行里面的代码。

代码实现:

// 初始化信号量,初始值为1(代表允许1个线程进入临界区)
private let logSemaphore = DispatchSemaphore(value: 1)

func write(_ text: String) {
    // 等待信号量,获取"锁"
    logSemaphore.wait()
    // defer保证不管代码怎么退出,都会释放信号量
    defer { logSemaphore.signal() }
    
    text.appendLineToURL(fileURL: self.path)
    sendLog(text)
}

注意:如果在同一个线程里递归调用write,会导致死锁——因为当前线程已经拿到了信号量,再次wait会一直等自己释放,永远卡着。所以这种方式要避免递归调用的场景。

3. 串行OperationQueue(灵活任务管理)

如果后续需要对日志任务做更灵活的控制(比如取消未执行的任务、添加任务依赖),可以用OperationQueue,把最大并发数设为1就变成了串行队列。

代码实现:

private let logOperationQueue = OperationQueue()

// 类初始化时配置队列
init() {
    logOperationQueue.maxConcurrentOperationCount = 1
    logOperationQueue.name = "com.yourapp.log.operation"
}

func write(_ text: String) {
    // 创建一个BlockOperation包装日志操作
    let logOperation = BlockOperation { [weak self] in
        guard let self = self else { return }
        text.appendLineToURL(fileURL: self.path)
        self.sendLog(text)
    }
    // 添加到串行队列执行
    logOperationQueue.addOperation(logOperation)
}

这种方式和串行队列本质类似,但Operation支持更多高级特性,适合复杂的任务场景。

总结

  • 大多数情况优先选串行DispatchQueue,简单、高效、无坑;
  • 需要任务管理灵活性选OperationQueue;
  • 信号量适合简单互斥,但要注意死锁风险。

内容的提问来源于stack exchange,提问作者Ginso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 10:30:59