Obj-C中@synchronized的key在Swift GCD中的等价实现是什么?
Obj-C @synchronized 与 Swift GCD 同步的等价机制
核心对应关系
@synchronized(obj) 本质是通过传入的obj作为唯一标识,为代码块创建互斥锁,保证同一时间仅一个线程能执行该代码。在GCD中,自定义串行队列是最直接的等价机制——你可以把这个队列当作"key",同一队列下的任务会串行执行,天然实现同步;另外也可以用**Dispatch Semaphore(信号量)**模拟基于对象的锁逻辑,更贴近@synchronized的锁语义。
方式一:自定义串行队列(推荐)
这是GCD中最常用的同步实现方式,和@synchronized的"key"思路完全对应:每个需要同步的逻辑对应一个专属串行队列,不同队列(不同key)之间的任务互不干扰。
Obj-C @synchronized 示例
@interface MyClass () @property (nonatomic, strong) NSObject *syncLock; @end @implementation MyClass - (instancetype)init { self = [super init]; if (self) { _syncLock = [[NSObject alloc] init]; } return self; } - (void)executeSyncTask { @synchronized(self.syncLock) { // 需要同步执行的代码 NSLog(@"执行同步任务"); } } @end
Swift GCD 等价实现
class MyClass { // 专属串行队列作为同步标识(对应@synchronized的key) private let syncQueue = DispatchQueue(label: "com.myapp.sync.queue") func executeSyncTask() { syncQueue.sync { // 需要同步执行的代码 print("执行同步任务") } } }
这里的syncQueue就等同于@synchronized里的syncLock对象,同一队列的任务会严格串行执行,保证线程安全。如果需要多组独立的同步逻辑,只需创建多个不同标识的串行队列即可。
方式二:Dispatch Semaphore(模拟对象锁)
如果想更贴近@synchronized"基于对象的互斥锁"语义,可以用信号量实现:为每个作为key的对象关联一个信号量,通过wait()和signal()控制代码块的访问权限。
Swift 示例
class MyClass { // 存储key与对应信号量的映射表 private var semaphoreMap = [AnyHashable: DispatchSemaphore]() // 保护映射表的串行队列(避免多线程读写冲突) private let mapAccessQueue = DispatchQueue(label: "com.myapp.semaphore.map") func executeSyncTask(withKey key: AnyHashable) { // 线程安全地获取或创建key对应的信号量 let semaphore = mapAccessQueue.sync { () -> DispatchSemaphore in if let existing = semaphoreMap[key] { return existing } let newSemaphore = DispatchSemaphore(value: 1) semaphoreMap[key] = newSemaphore return newSemaphore } semaphore.wait() defer { semaphore.signal() } // 需要同步执行的代码 print("基于key执行同步任务") } }
这种方式完全复刻@synchronized的底层逻辑,但实现复杂度高于串行队列,仅在需要严格匹配"对象作为锁key"的场景下使用。
注意事项
- 串行队列的
sync方法会阻塞当前线程,若在主线程调用可能引发死锁,无需等待执行结果时,优先用async更安全。 @synchronized会自动处理异常(代码块抛出异常也会释放锁);GCD串行队列天然无需手动释放锁,但信号量方式必须用defer确保signal()执行,避免死锁。
内容的提问来源于stack exchange,提问作者Snowtown123
相关产品推荐
相关产品推荐

