【线程】多线程同步互斥-互斥锁,生产者消费者问题

时间:2021-07-27 20:21:11

互斥锁

 

  互斥锁用来保证同一时间内只有一个线程在执行某段代码(临界区)。多线程编程最容易出问题的地方,就是临界区的界定和访问控制。

  下面是一个生产者,消费者的简单例子。生产者、消费者公用一个缓冲区,这里假定缓冲区只能存放一条消息。

 

生产者,消费者互斥

【线程】多线程同步互斥-互斥锁,生产者消费者问题【线程】多线程同步互斥-互斥锁,生产者消费者问题
 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 }
View Code

  

  输出一定是这样的:

【线程】多线程同步互斥-互斥锁,生产者消费者问题【线程】多线程同步互斥-互斥锁,生产者消费者问题
1 produce item
2 consumer item
3 produce item
4 consumer item
5 produce item
6 consumer item
7 produce item
8 consumer item
View Code

  

  互斥锁最简单的使用是这样的:

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_PRIVATEPTHREAD_PROCESS_SHARED

  1. 前者用来不同进程中的线程同步
  2. 后者用于同步本进程的不同线程。

  在上面的例子中,我们使用的是默认属性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)

 

  该函数超时返回。

  互斥锁主要用来互斥访问临界区。用于线程的互斥。