目录
概述
1. 互斥锁(Mutex)
2. 条件变量(Condition Variable)
3. 信号量(Semaphore)
4. 读写锁(Read-Write Lock)
5. 屏障(Barrier)
6. 自旋锁(Spinlock)
7. 线程局部存储(Thread-Local Storage, TLS)
总结
概述
Linux 中线程(Thread)是共享进程内存空间的轻量级执行单元,线程间通信(IPC)主要通过 共享内存 和 同步机制 实现。在Linux操作系统中,线程间实现同步通信的方式主要包括互斥锁(Mutex)、条件变量(Condition Variable)、信号量(Semaphore)、读写锁(Read-Write Lock)等。以下是常用方式及其原理、场景和代码示例。
1. 互斥锁(Mutex)
原理
-
通过锁机制保护共享资源,同一时间仅允许一个线程访问临界区。
-
线程在进入临界区前加锁,退出时解锁。
适用场景
-
保护共享变量、数据结构等临界资源。
-
防止数据竞争(Data Race)。
C 语言示例
#include <stdio.h>
#include <pthread.h>pthread_mutex_t mutex;
int counter = 0;void* thread_func(void* arg) {pthread_mutex_lock(&mutex); // 加锁counter++;printf("Counter: %d\n", counter);pthread_mutex_unlock(&mutex); // 解锁return NULL;
}int main() {pthread_t t1, t2;pthread_mutex_init(&mutex, NULL);pthread_create(&t1, NULL, thread_func, NULL);pthread_create(&t2, NULL, thread_func, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_mutex_destroy(&mutex);return 0;
}
2. 条件变量(Condition Variable)
原理
-
允许线程在条件不满足时阻塞,等待其他线程发送信号唤醒。
-
必须与互斥锁配合使用,避免竞争条件。
适用场景
-
生产者-消费者模型。
-
线程间状态同步(如任务队列空/满)。
C 语言示例
#include <stdio.h>
#include <pthread.h>pthread_mutex_t mutex;
pthread_cond_t cond;
int data_ready = 0;void* producer(void* arg) {pthread_mutex_lock(&mutex);data_ready = 1;printf("Producer: 数据已生成\n");pthread_cond_signal(&cond); // 发送信号pthread_mutex_unlock(&mutex);return NULL;
}void* consumer(void* arg) {pthread_mutex_lock(&mutex);while (!data_ready) {pthread_cond_wait(&cond, &mutex); // 等待信号}printf("Consumer: 收到数据\n");pthread_mutex_unlock(&mutex);return NULL;
}int main() {pthread_t prod, cons;pthread_mutex_init(&mutex, NULL);pthread_cond_init(&cond, NULL);pthread_create(&prod, NULL, producer, NULL);pthread_create(&cons, NULL, consumer, NULL);pthread_join(prod, NULL);pthread_join(cons, NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&cond);return 0;
}
3. 信号量(Semaphore)
原理
-
通过计数器控制资源访问,支持
P
(等待,计数器减)和V
(释放,计数器加)操作。 -
可以解决多线程同步问题,支持多个线程同时访问有限资源。
适用场景
-
控制资源池(如数据库连接池)。
-
限制并发线程数量。
C 语言示例
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>sem_t sem;
int shared_data = 0;void* thread_func(void* arg) {sem_wait(&sem); // P 操作shared_data++;printf("Thread %ld: shared_data = %d\n", (long)arg, shared_data);sem_post(&sem); // V 操作return NULL;
}int main() {sem_init(&sem, 0, 1); // 初始值为1(二进制信号量)pthread_t t1, t2;pthread_create(&t1, NULL, thread_func, (void*)1);pthread_create(&t2, NULL, thread_func, (void*)2);pthread_join(t1, NULL);pthread_join(t2, NULL);sem_destroy(&sem);return 0;
}
4. 读写锁(Read-Write Lock)
原理
-
允许多个读线程同时访问共享资源,但写线程独占访问。
-
读优先或写优先策略可选。
适用场景
-
读多写少的场景(如配置管理、缓存系统)。
C 语言示例
#include <stdio.h>
#include <pthread.h>pthread_rwlock_t rwlock;
int data = 0;void* reader(void* arg) {pthread_rwlock_rdlock(&rwlock); // 读锁printf("Reader: data = %d\n", data);pthread_rwlock_unlock(&rwlock);return NULL;
}void* writer(void* arg) {pthread_rwlock_wrlock(&rwlock); // 写锁data++;printf("Writer: 更新 data 为 %d\n", data);pthread_rwlock_unlock(&rwlock);return NULL;
}int main() {pthread_rwlock_init(&rwlock, NULL);pthread_t r1, r2, w;pthread_create(&r1, NULL, reader, NULL);pthread_create(&w, NULL, writer, NULL);pthread_create(&r2, NULL, reader, NULL);pthread_join(r1, NULL);pthread_join(w, NULL);pthread_join(r2, NULL);pthread_rwlock_destroy(&rwlock);return 0;
}
5. 屏障(Barrier)
原理
-
使多个线程在某个点同步,所有线程到达屏障后继续执行。
适用场景
-
并行计算中分阶段处理(如 MapReduce)。
C 语言示例
#include <stdio.h>
#include <pthread.h>pthread_barrier_t barrier;void* task(void* arg) {printf("线程 %ld 执行第一阶段\n", (long)arg);pthread_barrier_wait(&barrier); // 等待所有线程到达printf("线程 %ld 执行第二阶段\n", (long)arg);return NULL;
}int main() {pthread_barrier_init(&barrier, NULL, 3); // 等待3个线程pthread_t t1, t2, t3;pthread_create(&t1, NULL, task, (void*)1);pthread_create(&t2, NULL, task, (void*)2);pthread_create(&t3, NULL, task, (void*)3);pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_barrier_destroy(&barrier);return 0;
}
6. 自旋锁(Spinlock)
原理
-
线程在等待锁时不会休眠,而是循环检查锁状态(忙等待)。
-
适用于锁持有时间短的场景。
适用场景
-
内核编程或实时系统。
-
避免线程切换开销。
C 语言示例
#include <stdio.h>
#include <pthread.h>pthread_spinlock_t spinlock;
int counter = 0;void* thread_func(void* arg) {pthread_spin_lock(&spinlock);counter++;printf("Counter: %d\n", counter);pthread_spin_unlock(&spinlock);return NULL;
}int main() {pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE);pthread_t t1, t2;pthread_create(&t1, NULL, thread_func, NULL);pthread_create(&t2, NULL, thread_func, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_spin_destroy(&spinlock);return 0;
}
7. 线程局部存储(Thread-Local Storage, TLS)
原理
-
每个线程拥有变量的独立副本,互不干扰。
-
使用
__thread
关键字或pthread_key_create
实现。
适用场景
-
需要线程私有数据(如错误码、日志上下文)。
C 语言示例
#include <stdio.h>
#include <pthread.h>__thread int tls_var = 0; // GCC 扩展语法void* thread_func(void* arg) {tls_var = (int)(long)arg;printf("线程 %ld: tls_var = %d\n", (long)arg, tls_var);return NULL;
}int main() {pthread_t t1, t2;pthread_create(&t1, NULL, thread_func, (void*)1);pthread_create(&t2, NULL, thread_func, (void*)2);pthread_join(t1, NULL);pthread_join(t2, NULL);return 0;
}
总结
对比如下
根据具体场景选择合适的同步机制,例如:
-
高并发读 → 读写锁。
-
短临界区 → 自旋锁。
-
多阶段任务 → 屏障。