一、互斥量
/静态初始化
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *restrict mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_timelock(pthread_mutex_t *mutex,const struct timespec * time);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
头文件:#include <pthread.h>
返回值: 若成功,返回0;否则,返回错误编号
二、条件变量
int pthread_cond_init(pthread_cond_t* cond,pthread_condattr_t* attr);
int pthread_cond_signal(pthread_cond_t* cond);
int pthread_cond_broadcast(pthread_cond_t* cond);
int pthread_cond_wait(pthread_cond_t* cond,pthread_mutex_t* mutex);
从函数声明可以看出,两个函数都包含了互斥锁,所以,若某个线程因等待条件变量进入等待状态,将隐含的释放申请到的互斥锁,在返回时,将隐含的申请互斥锁,函数执行成功返回0。
下面是互斥锁和条件变量结合一起使用的生产者消费者的简单例子,但也是可以说明问题的:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int pro = 0;
pthread_mutex_t mutex;
pthread_cond_t cond;
void init()
{
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
}
void* producer(void* date)
{
while(1)
{
pthread_mutex_lock(&mutex);
pro++;
printf("生产者生产了1个,现在共%d个\n",pro);
if(pro == 3)
{
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
void* contomer(void* date)
{
while(1)
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
pro -= 3;
printf("消费者吃了3个\n");
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
void* ret;
pthread_t tid1,tid2;
init();
pthread_create(&tid1,NULL,producer,0);
pthread_create(&tid2,NULL,contomer,0);
pthread_join(tid1,&ret);
pthread_join(tid2,&ret);
return 0;
}
运行结果是:

从结果可以看出,当生产者生产了3个产品后,立即通知消费者来消费,紧接着,生产者继续生产,无线循环下去。里面需要注意的是消费者在调用pthread_cond_wait()后进入等待状态时,会把互斥锁解锁,并阻塞等待加锁后,才会继续消费。
三、读写锁
读写锁特性:
读写锁是"写模式加锁"时:解锁前,所有对该锁加锁的线程都会被阻塞。
读写锁是"读模式加锁"时:如果线程以读模式对其加锁会成功;如果线程以写模式加锁会阻塞。
读写锁是"读模式加锁"时:既有试图以写模式加锁的线程,也有试图以读模式加锁的线程。那么读写锁会阻塞随后的读模式锁请求。优先满足写模式锁。读锁、写锁并行阻塞,写锁优先级高
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);//初始化一把读写锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);//销毁一把读写锁
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_timewrlock(pthread_rwlock_t *rwlock,const struct timespec * time);//以写方式请求读写锁,指定超时时间
int pthread_rwlock_timerdlock(pthread_rwlock_t *rwlock,const struct timespec * time);//以读方式请求读写锁,指定超时时间
返回值: 若成功,返回0;否则,返回错误编号
四、自旋锁
自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,由于自旋锁使用者一般保持锁时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋锁的效率远高于互斥锁。自旋锁比较适用于锁使用者保持锁时间比较短的情况
int pthread_spin_destroy(pthread_spinlock_t *);
int pthread_spin_init(pthread_spinlock_t*, int);
int pthread_spin_lock(pthread_spinlock_t *);
int pthread_spin_trylock(pthread_spinlock_t *);
int pthread_spin_unlock(pthread_spinlock_t *);
五、屏障
屏障(barrier)是用户协调多个线程并行工作的同步机制。屏障允许每个线程等待,直到所有合作线程都到达某一点,然后从该点继续执行。
int pthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t * restrict attr, unsigned int count);
int pthread_barrier_destory(pthread_barrier_t * barrier);
int pthread_barrier_wait(pthread_barrier_t *barrier)

本文深入探讨了线程同步机制,包括互斥量、条件变量、读写锁、自旋锁和屏障的功能与使用方法。通过实例展示了这些机制如何帮助解决多线程编程中的资源竞争和同步问题。

476

被折叠的 条评论
为什么被折叠?



