GCD队列同步特性与锁机制结合实现线程安全代码
- 互斥锁与GCD结合
- 串行队列 + 互斥锁:使用串行队列确保任务顺序执行,减少竞争。同时,在访问共享资源前加互斥锁,例如使用
pthread_mutex_t
。代码示例:
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
dispatch_queue_t serialQueue = dispatch_queue_create("com.example.serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue, ^{
pthread_mutex_lock(&mutex);
// 访问共享资源
pthread_mutex_unlock(&mutex);
});
pthread_mutex_destroy(&mutex);
- 并发队列 + 互斥锁:并发队列可提高执行效率,但共享资源访问需加互斥锁保证安全。如:
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
pthread_mutex_lock(&mutex);
// 访问共享资源
pthread_mutex_unlock(&mutex);
});
pthread_mutex_destroy(&mutex);
- 读写锁与GCD结合
- 并发读:对于读操作,可以允许多个线程同时进行。使用读写锁(如
pthread_rwlock_t
),在并发队列中执行读任务时,加读锁。示例:
pthread_rwlock_t rwLock;
pthread_rwlock_init(&rwLock, NULL);
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
pthread_rwlock_rdlock(&rwLock);
// 执行读操作
pthread_rwlock_unlock(&rwLock);
});
pthread_rwlock_destroy(&rwLock);
- 独占写:写操作需要独占资源,在并发队列中执行写任务时,加写锁。示例:
pthread_rwlock_t rwLock;
pthread_rwlock_init(&rwLock, NULL);
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.example.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
pthread_rwlock_wrlock(&rwLock);
// 执行写操作
pthread_rwlock_unlock(&rwLock);
});
pthread_rwlock_destroy(&rwLock);
性能瓶颈分析
- 锁竞争:大量线程同时竞争锁,会导致线程阻塞,降低系统整体性能。例如在高并发写操作场景下,写锁竞争激烈,其他线程等待时间长。
- 队列等待:如果GCD队列任务过多,任务在队列中等待执行时间过长,导致响应延迟。特别是在串行队列中,前一个任务执行时间长,会影响后续任务。
性能优化方案
- 减少锁粒度:尽量缩小锁保护的代码范围,只对共享资源访问部分加锁。例如,将大段操作分解,使锁只保护关键数据访问部分,减少锁持有时间,降低锁竞争。
- 优化队列使用:根据任务特性合理选择队列。对于一些非关键任务,可放到低优先级队列执行;对于可并行的任务,使用并发队列并结合读写锁,提高执行效率。
- 读写分离:进一步优化读写操作,将读操作和写操作分别分配到不同的队列。读队列可使用并发队列提高读效率,写队列使用串行队列保证写操作顺序性和数据一致性。
- 使用信号量:对于一些需要控制并发数量的场景,可使用信号量(
dispatch_semaphore_t
)。比如限制同时访问共享资源的线程数量,避免过多线程竞争锁。