linux c 编程 ------ 线程间通信与同步机制

 

 

 

1、互斥锁

 常用函数:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);//互斥初始化
int pthread_mutex_destroy(pthread_mutex_t *mutex);//销毁互斥
int pthread_mutex_lock(pthread_mutex_t *mutex);//锁定互斥
int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁互斥
int pthread_mutex_trylock(pthread_mutex_t *mutex);//非阻塞的锁定互斥锁

 2、条件变量

pthread_cond_wait 自动解锁互斥量(如同执行了pthread_unlock_mutex),并等待条件变量触发。这时线程挂起,不占用CPU时间,直到条件变量被触发(变量为true)。在调用 pthread_cond_wait之前,应用程序必须加锁互斥量。pthread_cond_wait函数返回前,自动重新对互斥量加锁(如同执行了pthread_lock_mutex)。

使用案例:

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int data_ready = 0;

void* producer(void* arg) {
    // 生成数据
    pthread_mutex_lock(&mutex);
    data_ready = 1;
    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); // 等待生产者通知
    }
    // 消费数据
    pthread_mutex_unlock(&mutex);
    return NULL;
}

 

 唤醒条件有两种形式,pthread_cond_signal()唤醒一个等待该条件的线程,存在多个等待线程时按入队顺序唤醒其中一个;而pthread_cond_broadcast()则唤醒所有等待线程

 3、信号量

函数:

int sem_init (sem_t *sem , int pshared, unsigned int value);
int sem_post(sem_t *sem);
int sem_wait(sem_t *sem);
int sem_destroy(sem_t *sem);

 4、读写锁

1.如果一个线程用读锁锁定了临界区,那么其他线程也可以用读锁来进入临界区,这样就可以多个线程并行操作。但这个时候,如果再进行写锁加锁就会发生阻塞,写锁请求阻塞后,后面如果继续有读锁来请求,这些后来的读锁都会被阻塞!这样避免了读锁长期占用资源,防止写锁饥饿!

2.如果一个线程用写锁锁住了临界区,那么其他线程不管是读锁还是写锁都会发生阻塞!

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict abs_timeout);

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);

5、内存屏障 

POSIX线程库提供了pthread_barrier,这是一种专门用于线程同步的屏障机制。屏障允许一组线程在某个点上等待,直到所有线程都到达该点,然后所有线程才能继续执行。

使用场景

  • 当多个线程需要并行执行某些任务,但在某个关键点上需要同步时(例如,并行计算中的迭代同步)。
  • 确保所有线程在继续执行之前完成某些初始化或计算。
#include <pthread.h>
#include <stdio.h>

#define NUM_THREADS 4
pthread_barrier_t barrier;

void* thread_func(void* arg) {
    int thread_id = *(int*)arg;
    printf("Thread %d: Doing some work...\n", thread_id);
    
    // 模拟工作
    sleep(1);
    
    printf("Thread %d: Reached the barrier.\n", thread_id);
    pthread_barrier_wait(&barrier); // 等待所有线程到达屏障
    
    printf("Thread %d: All threads have passed the barrier. Continuing...\n", thread_id);
    return NULL;
}

int main() {
    pthread_t threads[NUM_THREADS];
    int thread_ids[NUM_THREADS];
    
    // 初始化屏障
    pthread_barrier_init(&barrier, NULL, NUM_THREADS + 1); // +1 是因为主线程可能也需要等待
    
    for (int i = 0; i < NUM_THREADS; i++) {
        thread_ids[i] = i;
        pthread_create(&threads[i], NULL, thread_func, &thread_ids[i]);
    }
    
    // 主线程也可以等待屏障(可选)
    printf("Main thread: Waiting for threads...\n");
    pthread_barrier_wait(&barrier);
    printf("Main thread: All threads have passed the barrier.\n");
    
    for (int i = 0; i < NUM_THREADS; i++) {
        pthread_join(threads[i], NULL);
    }
    
    // 销毁屏障
    pthread_barrier_destroy(&barrier);
    
    return 0;
}

 

posted @ 2020-04-15 17:44  流水灯  阅读(27)  评论(0)    收藏  举报