在多线程编程中,多个线程共享资源时容易出现数据不一致的问题。因此,掌握线程同步与互斥技术至关重要。本文将深入讲解Linux下的同步互斥机制,从最基本的锁机制到经典的生产者消费者模型,帮助小白轻松理解。
互斥是指保证同一时间只有一个线程访问共享资源,防止数据竞争;而线程同步则是在互斥的基础上,协调线程的执行顺序,例如生产者必须在缓冲区有空间时才能生产,消费者必须在缓冲区有数据时才能消费。两者共同保证了多线程程序的正确性。
互斥锁是最基本的同步工具,用于保护临界区。在Linux中,使用pthread_mutex_t类型。基本操作包括初始化、加锁、解锁和销毁。下面是一个简单的示例:
#include pthread_mutex_t mutex;void* worker(void* arg) { pthread_mutex_lock(&mutex); // 临界区代码 printf("线程安全操作"); pthread_mutex_unlock(&mutex); return NULL;}int main() { pthread_t t1, t2; pthread_mutex_init(&mutex, NULL); pthread_create(&t1, NULL, worker, NULL); pthread_create(&t2, NULL, worker, NULL); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_mutex_destroy(&mutex); return 0;} 注意:加锁后一定要在适当位置解锁,否则会导致死锁。
当两个或多个线程互相等待对方释放锁时,就会发生死锁。常见的避免方法包括:固定加锁顺序、使用trylock、避免锁嵌套等。
条件变量用于线程间等待某个条件成立,通常与互斥锁配合使用。它允许线程在条件不满足时阻塞,并释放锁,当条件满足时由其他线程唤醒。下面是一个使用条件变量的简单示例:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t cond = PTHREAD_COND_INITIALIZER;int ready = 0;void* waiter(void* arg) { pthread_mutex_lock(&mutex); while (!ready) { pthread_cond_wait(&cond, &mutex); } printf("条件满足,继续执行"); pthread_mutex_unlock(&mutex); return NULL;}void* signaller(void* arg) { pthread_mutex_lock(&mutex); ready = 1; pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); return NULL;} 这里waiter等待ready变为真,signaller设置ready并唤醒waiter。
信号量是一种更高级的同步机制,可以控制多个线程对资源的访问。POSIX信号量用sem_t表示,主要操作有sem_wait(P操作)和sem_post(V操作)。信号量常用于实现生产者消费者模型中的计数同步。
#include sem_t sem;sem_init(&sem, 0, 1); // 初始值为1,相当于互斥锁sem_wait(&sem); // P操作,减1,如果为0则阻塞// 临界区sem_post(&sem); // V操作,加1,唤醒等待线程sem_destroy(&sem); 读写锁允许多个线程同时读共享数据,但写操作必须独占。适用于读多写少的场景,可提高并发性。Linux中使用pthread_rwlock_t类型。
生产者消费者模型是多线程编程的经典问题,涉及有限缓冲区。下面用互斥锁和条件变量实现一个简单的模型:
#include #include #define BUFFER_SIZE 5int buffer[BUFFER_SIZE];int count = 0;int in = 0, out = 0;pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t not_full = PTHREAD_COND_INITIALIZER;pthread_cond_t not_empty = PTHREAD_COND_INITIALIZER;void* producer(void* arg) { int item = 0; while (1) { pthread_mutex_lock(&mutex); while (count == BUFFER_SIZE) { pthread_cond_wait(¬_full, &mutex); } buffer[in] = item++; in = (in + 1) % BUFFER_SIZE; count++; printf("生产了 %d,缓冲区大小:%d", item-1, count); pthread_cond_signal(¬_empty); pthread_mutex_unlock(&mutex); } return NULL;}void* consumer(void* arg) { while (1) { pthread_mutex_lock(&mutex); while (count == 0) { pthread_cond_wait(¬_empty, &mutex); } int item = buffer[out]; out = (out + 1) % BUFFER_SIZE; count--; printf("消费了 %d,缓冲区大小:%d", item, count); pthread_cond_signal(¬_full); pthread_mutex_unlock(&mutex); } return NULL;} 生产者等待缓冲区不满,消费者等待缓冲区不空,通过条件变量进行同步。这个模型完美体现了线程同步与互斥的结合。
本文详细介绍了Linux下的线程同步与互斥机制,包括互斥锁、条件变量、信号量和读写锁,并通过生产者消费者模型展示了它们的实际应用。掌握这些知识,你就能编写出安全高效的多线程程序。记住,线程同步和互斥锁是基础,条件变量和信号量是强大工具,而生产者消费者模型则是经典案例,反复练习才能融会贯通。
本文由主机测评网于2026-02-28发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://vpshk.cn/20260227770.html