linux线程锁有几种
在 Linux 系统中,线程锁(线程同步机制)主要有以下几种类型,每种锁适用于不同的并发场景:
1. 互斥锁(Mutex)
- 作用:确保同一时间只有一个线程能访问共享资源。
- 特点:
- 阻塞机制:未获取锁的线程会阻塞等待。
- 不可重入:默认情况下,同一线程重复加锁会导致死锁(但可通过属性配置为可重入锁)。
- 相关函数:
c
pthread_mutex_init() / pthread_mutex_lock() / pthread_mutex_unlock() / pthread_mutex_destroy()
- 适用场景:对共享资源的独占访问(如全局变量、数据结构等)。
2. 自旋锁(Spinlock)
- 作用:通过忙等待(Busy-Waiting)实现同步,线程不会主动让出CPU。
- 特点:
- 非阻塞忙等待:适合短时间锁持有场景。
- 无上下文切换开销,但会占用CPU资源。
- 相关函数:
c
pthread_spin_init() / pthread_spin_lock() / pthread_spin_unlock() / pthread_spin_destroy()
- 适用场景:多核CPU环境,锁持有时间极短(如内核态操作、高性能场景)。
3. 读写锁(Read-Write Lock)
- 作用:区分读操作和写操作,允许多个读线程并发,但写线程独占。
- 特点:
- 读共享:多个线程可同时持有读锁。
- 写独占:写锁会阻塞其他所有读写锁。
- 相关函数:
c
pthread_rwlock_init() / pthread_rwlock_rdlock() / pthread_rwlock_wrlock() / pthread_rwlock_unlock()
- 适用场景:读多写少的场景(如缓存、配置文件读取)。
4. 条件变量(Condition Variable)
- 作用:允许线程在某个条件不满足时主动阻塞,等待其他线程唤醒。
- 特点:
- 必须与互斥锁配合使用。
- 通过
pthread_cond_wait()
主动释放锁并进入等待,被唤醒后重新获取锁。
- 相关函数:
c
pthread_cond_init() / pthread_cond_wait() / pthread_cond_signal() / pthread_cond_broadcast()
- 适用场景:线程间协作(如生产者-消费者模型)。
5. 屏障(Barrier)
- 作用:同步多个线程,所有线程到达屏障点后才能继续执行。
- 特点:
- 相关函数:
c
pthread_barrier_init() / pthread_barrier_wait() / pthread_barrier_destroy()
- 适用场景:多线程协同计算(如MapReduce分阶段处理)。
6. 信号量(Semaphore)
- 作用:通过计数器控制线程并发数(POSIX信号量)。
- 特点:
- 分为有名信号量(进程间共享)和无名信号量(线程间共享)。
- 支持
P
(sem_wait
)和 V
(sem_post
)操作。
- 相关函数:
c
sem_init() / sem_wait() / sem_post() / sem_destroy()
- 适用场景:限制资源并发访问数量(如线程池任务队列)。
7. 文件锁(fcntl/flock)
- 作用:对文件或文件区域加锁(进程间同步)。
- 特点:
- 分为建议性锁(Advisory)和强制性锁(Mandatory)。
- 相关函数:
c
fcntl() / flock()
- 适用场景:多进程访问同一文件的同步。
选择锁的建议
- 简单独占访问 → 互斥锁(Mutex)。
- 高频短时锁 → 自旋锁(Spinlock)。
- 读多写少 → 读写锁(RW Lock)。
- 线程协作 → 条件变量 + 互斥锁。
- 限制并发数 → 信号量(Semaphore)。
注意事项
- 避免死锁:确保锁的获取和释放顺序一致。
- 性能权衡:自旋锁 vs 互斥锁取决于锁持有时间。
- 可重入性:默认互斥锁不可重入,需通过属性设置
PTHREAD_MUTEX_RECURSIVE
。
根据具体场景选择合适的锁机制,可以显著提升多线程程序的性能和可靠性。