在 C 语言中,常见的互斥同步工具和机制主要是基于 POSIX 标准,通常用于线程间的同步,保证在并发执行时共享资源的正确性。以下是常见的同步工具总结:
1. 互斥锁(Mutex)
互斥锁用于保护共享资源,确保在同一时刻只有一个线程可以访问共享资源。
- 头文件:
#include <pthread.h>
初始化:
使用
pthread_mutex_init()
初始化:1
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
或者显式初始化:
1
2pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
常用操作:
- 加锁:
pthread_mutex_lock(&mutex);
- 如果锁已经被其他线程占用,调用线程将被阻塞。
- 尝试加锁(非阻塞):
pthread_mutex_trylock(&mutex);
- 如果锁被占用,立即返回错误代码。
- 解锁:
pthread_mutex_unlock(&mutex);
- 释放锁,其他线程可以继续访问。
销毁:
pthread_mutex_destroy(&mutex);
- 在不再使用时销毁互斥锁。
2. 读写锁(Read-Write Lock)
读写锁允许多个线程同时读取资源,但在写入资源时会阻塞其他线程的读写操作。
- 头文件:
#include <pthread.h>
初始化:
使用
pthread_rwlock_init()
初始化:1
2pthread_rwlock_t rwlock;
pthread_rwlock_init(&rwlock, NULL);
常用操作:
- 读锁:
pthread_rwlock_rdlock(&rwlock);
- 允许多个线程同时获得读锁,但如果写锁被持有,读线程会被阻塞。
- 写锁:
pthread_rwlock_wrlock(&rwlock);
- 只有一个线程可以获得写锁,且会阻塞所有读锁和写锁请求。
- 释放读写锁:
pthread_rwlock_unlock(&rwlock);
- 释放当前持有的锁。
销毁:
pthread_rwlock_destroy(&rwlock);
3. 条件变量(Condition Variable)
条件变量用于在线程之间传递信号,常与互斥锁结合使用,用于实现线程等待与通知机制。
- 头文件:
#include <pthread.h>
初始化:
使用
pthread_cond_init()
初始化:1
2pthread_cond_t cond;
pthread_cond_init(&cond, NULL);
常用操作:
- 等待条件:
pthread_cond_wait(&cond, &mutex);
- 等待某个条件发生,线程在此调用会释放互斥锁,直到被通知才重新获取锁。
- 发送通知:
pthread_cond_signal(&cond);
- 通知一个正在等待的线程。
- 广播通知:
pthread_cond_broadcast(&cond);
- 通知所有等待线程。
销毁:
pthread_cond_destroy(&cond);
4. 信号量(Semaphore)
信号量用于控制多个线程访问共享资源的数量,适用于限制并发数量。
- 头文件:
#include <semaphore.h>
初始化:
使用
sem_init()
初始化:1
2sem_t sem;
sem_init(&sem, 0, 1); // 第二个参数为0表示该信号量是线程间使用
常用操作:
- 获取信号量:
sem_wait(&sem);
- 阻塞当前线程,直到信号量大于0,执行后信号量减1。
- 释放信号量:
sem_post(&sem);
- 释放信号量,信号量加1。
销毁:
sem_destroy(&sem);
5. 自旋锁(Spinlock)
自旋锁是一种轻量级锁,适用于短时间内争用的场景,线程会在获取锁时持续自旋等待。
- 头文件:
#include <pthread.h>
初始化:
使用
pthread_spin_init()
初始化:1
2pthread_spinlock_t spinlock;
pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE);
常用操作:
- 加锁:
pthread_spin_lock(&spinlock);
- 自旋等待获取锁。
- 解锁:
pthread_spin_unlock(&spinlock);
- 释放锁。
销毁:
pthread_spin_destroy(&spinlock);
6. 屏障(Barrier)
屏障用于同步多个线程,在屏障处,线程必须等到所有线程到达后才会继续执行。
- 头文件:
#include <pthread.h>
初始化:
使用
pthread_barrier_init()
初始化:1
2pthread_barrier_t barrier;
pthread_barrier_init(&barrier, NULL, 3); // 3个线程需要在屏障点同步
常用操作:
- 等待屏障:
pthread_barrier_wait(&barrier);
- 每个线程都会在此调用阻塞,直到所有线程都到达屏障点。
销毁:
pthread_barrier_destroy(&barrier);
总结
这些同步机制各自有不同的适用场景:
- 互斥锁(Mutex):常用于保护共享资源,确保数据一致性。
- 读写锁(Read-Write Lock):适合于读多写少的场景,可以提升读操作的并发性。
- 条件变量(Condition Variable):用于线程间的通信和同步,解决生产者-消费者问题等。
- 信号量(Semaphore):控制资源的并发访问,常用于限制并发线程的数量。
- 自旋锁(Spinlock):适用于锁竞争非常短暂的情况。
- 屏障(Barrier):用于多线程的同步,确保所有线程在某个点上同步执行。
这些工具的选择应根据实际需求来进行,既要考虑性能,也要保证数据的一致性和程序的正确性。