互斥锁 生产者和消费者模型 读写锁
互斥锁两者相互斥没有办法两个同时运行lock 加锁堵塞 unlock 解锁pthread_mutex_init()//互斥锁初始化 pthread_mutex_lock()//互斥锁上锁 pthread_mutex_unlock()//互斥锁解锁 ont pthread_mutex_destroy()//互斥锁销毁互斥锁的初始化函数模型int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr) mutex:指向 pthread_mutex_t 的指针初始化该地址的变量 attr:执行pthread_mutex_t的指针用于制定互斥锁的属性通常为NULL上锁 解锁int pthread_mutex_lock(pthread_mutex_t *mutex) mutex:指向pthread_mutex_t的指针用于对创建的互斥锁上锁int pthread_mutex_unlock(pthread_mutex_t *mutex) mutex:指向pthread_mutex_t的指针用于对创建的互斥锁解锁销毁锁int pthread_mutex_destory(pthread_mutex_t *mutex)销毁该互斥锁生产者和消费者模型生产者和消费者模型:两个或多个线程共享同一缓冲区其中一个线程作为“生产者”的角色不断为缓冲区添加资源”,而“消费者“取走数据1.生产者和消费者必须互斥使用缓冲区2.缓冲区满时生产者不能生产资源3.缓冲区空时消费者不能获取资源两个生产者 4个消费者最大支持4个线程运行#includestdio.h #includestdlib.h #includeunistd.h #includepthread.h #includesemaphore.h #includestring.h#includestdio.h #includestdlib.h #includeunistd.h #includepthread.h #includesemaphore.h #includestring.h #define NUM 30 int buffer[NUM]; //资源大小 sem_t sem_full; sem_t sem_empty; pthread_mutex_t mutex; //互斥锁 int main() { //对信号量的初始化 sem_init(sem_empty, 0, NUM); //生产者初始信号量值 //取地址 默认属性 信号量的范围 sem_init(sem_full, 0, 0); //消费者初始信号量值 pthread_mutex_init(mutex,NULL); pthread_t sc_id[2];//生产者的线程个数 pthread_t xf_id[4];//消费者的线程个数 //创建两个生产者 4个消费者最大支持4个线程运行 for(int i0;i2;i) pthread_create(sc_id[i],NULL,sc_thread,NULL); for(int i0;i4;i) pthread_create(sc_id[i],NULL,xf_thread,NULL); //同理 等待 for(int i0;i2;i) pthread_join(sc_id[i],NULL); for(int i0;i4;i) pthread_join(sc_id[i],NULL); //同理 销毁 sem_destroy(sem_full); sem_destroy(sem_empty); pthread_attr_destroy(mutex); exit(0); }生产者void *sc_thread(void* arg) { for(int i0;i30;i) { sem_wait(sem_empty);//让生产者先制造资源 pthread_mutex_lock(mutex);//上所保证互斥 //生产者角色在线程中做的事情 buffer[in]rand()%100; printf(生产者在%d处生产了数据%d,in,buffer[in]); in(in1)%NUM; pthread_mutex_unlock(mutex); sem_post(sem_full);//生产者生产完毕消费者可以运行去获取数据 } }消费者//消费者 void *xf_thread(void* arg) { for(int i0;i30;i) { sem_wait(sem_full);//让消费者开始消费资源 pthread_mutex_lock(mutex);//上所保证互斥 //消费者角色在线程中做的事情 buffer[out]rand()%100; printf(消费者在%d处消费了数据%d\n,out,buffer[out]); out( out 1 )%NUM; pthread_mutex_unlock(mutex); sem_post(sem_empty);//消费者消费完毕生产者可以继续去生产数据 } }完整版#includestdio.h #includestdlib.h #includeunistd.h #includepthread.h #includesemaphore.h #includestring.h #define NUM 30 int buffer[NUM]; //资源大小 int in10;//对缓冲区的位置下标制造资源 int out;//对缓冲区的位置下标消耗资源 sem_t sem_full; sem_t sem_empty; pthread_mutex_t mutex; //互斥锁 //生产者 void *sc_thread(void* arg) { for(int i0;i30;i) { sem_wait(sem_empty);//让生产者先制造资源 pthread_mutex_lock(mutex);//上所保证互斥 //生产者角色在线程中做的事情 buffer[in]rand()%100; printf(生产者在%d处生产了数据%d\n,in,buffer[in]); in(in1)%NUM; pthread_mutex_unlock(mutex); sem_post(sem_full); //生产者生产完毕消费者可以运行去获取数据 } } //消费者 void *xf_thread(void* arg) { for(int i0;i30;i) { sem_wait(sem_full);//让消费者开始消费资源 pthread_mutex_lock(mutex);//上所保证互斥 //消费者角色在线程中做的事情 buffer[out]rand()%100; printf(消费者在%d处消费了数据%d\n,out,buffer[out]); out( out 1 )%NUM; pthread_mutex_unlock(mutex); sem_post(sem_empty);//消费者消费完毕生产者可以继续去生产数据 } } int main() { //对信号量的初始化 sem_init(sem_empty, 0, NUM); //生产者初始信号量值 //取地址 默认属性 信号量的范围 sem_init(sem_full, 0, 0); //消费者初始信号量值 pthread_mutex_init(mutex,NULL); pthread_t sc_id[2];//生产者的线程个数 pthread_t xf_id[4];//消费者的线程个数 //创建两个生产者 4个消费者最大支持4个线程运行 for(int i0;i2;i) pthread_create(sc_id[i],NULL,sc_thread,NULL); for(int i0;i4;i) pthread_create(sc_id[i],NULL,xf_thread,NULL); //同理 等待 for(int i0;i2;i) pthread_join(sc_id[i],NULL); for(int i0;i4;i) pthread_join(sc_id[i],NULL); //同理 销毁 sem_destroy(sem_full); sem_destroy(sem_full); pthread_mutex_destroy(mutex); exit(0); }读写锁: 读操作不互斥写操作必须互斥读读不影响读写不行写写也不行读锁:共享锁可以被多个线程持有只要没有线程持有写锁写锁:独占锁只能被一个线程持有且不允许任何进程持有读锁pthread_rwlock_init() //读写锁初始化int pthread_rwlock_init( pthread_rwlock_t *restrict rwlock, const pthread_rwlock_t*restrict attr)rwlock:指向要初始化的读写锁attr: 读写锁的属性通常设为NULLpthread_rwlock_destroy(pthread_rwlock_t *restrict rwlock)//销毁读写锁pthread_rwlock_rdlock() //加读锁函数会暂时被堵塞直到获取到读锁才继续运行 pthread_rwlock_wrlock() //加写锁函数会暂时被堵塞直到获取到写锁才继续运行 pthread_rwlock_unlock() //解锁互斥锁 | 读写锁任意时刻只有一个线程运行 | 允许多个读者同时运行但写者必须独占资源规则:只要有线程持有锁其他线程必须等待 | 持有读锁时可继续加读锁;持有写锁时独占场景:读写较为频繁读和写的频率一致 | 读多写少的情况条件变量:某些情况下启动线程时会需要一个前提条件例如生产消费模型如果没有条件变量cpu会不断的轮询该条件导致CPU性能浪费,所以采用条件变量的方法。等待操作:当线程调用条件变量的等待函数时该线程会释放与条件变量无关的互斥锁并进入堵塞状态直到被其他线程唤醒通知操作:分两种signal用于唤醒一个等待在条件变量上的线程broadcast会唤醒所有等待该条件变量的线程。