【线程】多线程同步互斥-互斥锁,生产者消费者问题
互斥锁
互斥锁用来保证同一时间内只有一个线程在执行某段代码(临界区)。多线程编程最容易出问题的地方,就是临界区的界定和访问控制。
下面是一个生产者,消费者的简单例子。生产者、消费者公用一个缓冲区,这里假定缓冲区只能存放一条消息。
生产者,消费者互斥
1 //生产者,消费者问题 2 //生产者、消费者公用一个缓冲区,这里假定缓冲区只能存放一条消息。 3 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <pthread.h> 8 #include <sys/time.h> 9 10 static char buff[50]; 11 int have_msg=0; 12 pthread_mutex_t mutex; 13 int delay=1; 14 15 void consumeItem(char *buff) 16 { 17 printf("consumer item\n"); 18 } 19 20 void produceItem(char *buff) 21 { 22 printf("produce item\n"); 23 } 24 25 void *consumer(void *param)//消费者进程回调函数 26 { 27 while (1) 28 { 29 pthread_mutex_lock(&mutex); 30 if (have_msg>0) 31 { 32 have_msg--; 33 consumeItem(buff); 34 } 35 pthread_mutex_unlock(&mutex); 36 sleep(delay); 37 } 38 return NULL; 39 } 40 41 void *producer(void *param)//生产者进程回调函数 42 { 43 while (1) 44 { 45 pthread_mutex_lock(&mutex); 46 if (have_msg==0) 47 { 48 have_msg++; 49 produceItem(buff); 50 } 51 pthread_mutex_unlock(&mutex); 52 sleep(delay); 53 } 54 return NULL; 55 } 56 57 //主函数 58 int main() 59 { 60 pthread_t tid_c, tid_p; 61 void *retval; 62 63 pthread_mutex_init(&mutex, NULL);//默认属性初始化锁 64 65 pthread_create(&tid_p, NULL, producer, NULL); 66 pthread_create(&tid_c, NULL, consumer, NULL); 67 68 pthread_join(tid_p, &retval); 69 pthread_join(tid_c, &retval); 70 71 return 0; 72 }
输出一定是这样的:
1 produce item 2 consumer item 3 produce item 4 consumer item 5 produce item 6 consumer item 7 produce item 8 consumer item
互斥锁最简单的使用是这样的:
pthread_mutex_t mutex; //定义锁 pthread_mutex_init(&mutex, NULL); //默认属性初始化锁 pthread_mutex_lock(&mutex); //申请锁 ... pthread_mutex_unlock(&mutex); //释放锁
设置锁的属性
函数pthread_mutexattr_setpshared和函数pthread_mutexattr_settype用来设置互斥锁属性。
前者设置属性pshared,它有两个取值,PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED。
- 前者用来不同进程中的线程同步
- 后者用于同步本进程的不同线程。
在上面的例子中,我们使用的是默认属性PTHREAD_PROCESS_ PRIVATE。
后者用来设置互斥锁类型,可选的类型有PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_ERRORCHECK、PTHREAD_MUTEX_RECURSIVE和PTHREAD _MUTEX_DEFAULT。
它们分别定义了不同的上所、解锁机制,一般情况下,选用最后一个默认属性。
用法如下:
1 pthread_mutexattr_t mutexAttr; 2 pthread_mutexattr_init(&mutexAttr); 3 pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_PRIVATE); 4 pthread_mutexattr_settype(&mutexAttr, PTHREAD_MUTEX_DEFAULT); 5 pthread_mutex_init(&mutex, &mutexAttr);
pthread_mutex_lock阻塞线程直到pthread_mutex_unlock被调用。
还有另外两个函数可以用:
int pthread_mutex_trylock (pthread_mutex_t *__mutex)
该函数立即返回,根据返回状态判断加锁是否成功。
int pthread_mutex_timedlock (pthread_mutex_t *mutex, struct timespec *__restrict)
该函数超时返回。
互斥锁主要用来互斥访问临界区。用于线程的互斥。