1 互斥锁
1.1 互斥锁函数
- pthread_mutex_init:创建互斥锁
- pthread_mutex_lock:锁定
- pthread_mutex_unlock:解锁
- pthread_mutex_destroy:删除互斥锁
1.2 互斥锁示例
#include <pthread.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <stdlib.h>#include <stdio.h>int run_now=1; /*用run_now代表共享资源*/pthread_mutex_t work_mutex; /*定义互斥量*/void *thread_function(void *arg){sleep(1);/*对互斥量加锁*/if(pthread_mutex_lock(&work_mutex)!=0){perror("Lock failed");exit(1);}elseprintf("function lock\n");for (int i=0; i<5; i++){/*分线程:如果run_now为1就把它修改为1*/if(run_now==2){printf("function thread is run\n");run_now=1;}else{printf("function thread is sleep\n");sleep(1);}}/*对互斥量解锁*/if(pthread_mutex_unlock(&work_mutex)!=0){perror("unlock failed");exit(1);}elseprintf("function unlock\n");pthread_exit(NULL);}int main(){pthread_t a_thread;if(pthread_mutex_init(&work_mutex,NULL)!=0) /*初始化互斥量*/{perror("Mutex init faied");exit(1);}if(pthread_create(&a_thread,NULL,thread_function,NULL)!=0) /*创建新线程*/{perror("Thread createion failed");exit(1);}if(pthread_mutex_lock(&work_mutex)!=0) /*对互斥量加锁*/{perror("Lock failed");exit(1);}elseprintf("main lock\n");for (int i=0; i<5; i++){if(run_now == 1) /*主线程:如果run_now为1就把它修改为2*/{printf("main thread is run\n");run_now=2;}else{printf("main thread is sleep\n");sleep(1);}}if(pthread_mutex_unlock(&work_mutex)!=0) /*对互斥量解锁*/{perror("unlock failed");exit(1);}elseprintf("main unlock\n");pthread_join(a_thread,NULL); /*等待子线程结束*/pthread_mutex_destroy(&work_mutex); /*收回互斥量资源*/exit(0);}
2 自旋锁
当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。
减少了不必要的上下文切换,但会加剧CPU消耗。
- pthread_spin_init
- pthread_spin_destroy
- pthread_spin_lock
- pthread_spin_unlock
3 读写锁
- 读锁之间是共享的:即一个线程持有了读锁之后,其他线程也可以以读的方式持有这个锁
- 写锁之间是互斥的:即一个线程持有了写锁之后,其他线程不能以读或者写的方式持有这个锁
读写锁之间是互斥的:即一个线程持有了读锁之后,其他线程不能以写的方式持有这个锁
Pthread_rwlock_init
- Pthread_rwlock_destory
- Pthread_rwlock_rdlock
- Pthread_rwlock_wrlock
- Pthread_rwlock_unlock
4 POSIX条件变量
当一个线程互斥的访问某个变量时,需要等待其他线程改变变量状态之后才能访问。这样的变量要设置成条件变量。
头文件
#include <pthread.h>
4.1 条件变量函数
- pthread_cond_init:初始化条件变量
- pthread_cond_destroy:删除条件变量
- pthread_cond_wait:在一个指定的条件上等待。具体执行逻辑如下
- 对第二个参数的互斥锁解锁
- 等待条件,知道有线程发起条件满足通知
- 对互斥锁重新加锁
- pthread_cond_signal:当条件满足时,向指定线程发送通知。如果没有线程wait,通知被丢弃。
- pthread_cond_broadcast:当条件满足时,向所有线程发送通知
条件变量通常与互斥锁配合使用,条件变量使用规范如下:
等待条件代码
pthread_mutex_lock(&mutex); //锁定互斥量//这里用while是为了防止虚假唤醒,如果是虚假唤醒,条件并没有改变,需要用while再次判断条件是否满足while(条件为假)pthread_cond_wait(cond,mutex);修改条件pthread_mutex_unlock(&mutex);
给线程发送信号代码
pthread_mutex_lock(&mutex);设置条件为真pthread_cond_signal(cond);pthread_mutex_unlock(&mutex);
4.2 生产者消费者问题示例
```c
include
include
include
include
include
include
include
define ERR_EXIT(m) \
do \{ \perror(m); \exit(EXIT_FAILURE); \}while(0)
define CONSUMERS_COUNT 2
define PRODUCERS_COUNT 4
pthread_cond_t g_cond; pthread_mutex_t g_mutex;
// 创建的线程ID保存在g_thread中 pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT];
int nready=0;
///消费者 void consume(void arg) { //most platforms pointers and longs are the same size, but ints and pointers often are not the same size on 64bit platforms int num = (long)arg; while(1) { pthread_mutex_lock(&g_mutex); while(nready == 0) { printf(“(%d)begin wait a condition….\n”,num); pthread_cond_wait(&g_cond,&g_mutex); } printf(“(%d) end wait a condition….\n”,num); printf(“(%d) begin consume product ….\n”,num); —nready; printf(“(%d) end consume product ….\n”,num); pthread_mutex_unlock(&g_mutex); sleep(1); } return NULL; }
//// 生产者 void produce(void arg) { //most platforms pointers and longs are the same size, but ints and pointers often are not the same size on 64bit platforms int num = (long)arg; while(1) { pthread_mutex_lock(&g_mutex); printf(“ (%d) begin produce product …\n”,num); ++nready; printf(“ (%d) end produce product….\n”,num); pthread_cond_signal(&g_cond); printf(“ (%d) signal \n”,num); pthread_mutex_unlock(&g_mutex); sleep(5); } return NULL; }
int main(void ) { //初始化互斥锁 pthread_mutex_init(&g_mutex,NULL); //初始化条件变量 pthread_cond_init(&g_cond,NULL);
/// 创建消费者线程for(int i=0; i<CONSUMERS_COUNT; i++)pthread_create(&g_thread[i],NULL,consume,(void*)i);sleep(1);/// 创建生产者线程for(int i=0; i<PRODUCERS_COUNT; i++)pthread_create(&g_thread[CONSUMERS_COUNT+i],NULL,produce,(void*)i);// 等待线程的结束for(int i=0; i<CONSUMERS_COUNT+PRODUCERS_COUNT; i++)pthread_join(g_thread[i],NULL);//销毁互斥锁和条件变量pthread_mutex_destroy(&g_mutex);pthread_cond_destroy(&g_cond);return 0;
} ```
