Linux利用信号量实现线程的同步与互斥

线程使用互斥锁可以实现线程间的互斥,而互斥锁本身就是对资源的一种标识状态,当可以申请到锁时说明此时资源可以使用,当申请锁失败时说明资源此时被其他线程所占用不可使用,我们可以使用信号量来代替互斥锁实现。
信号量用来表示资源数目,当一个线程要去访问资源时,必须先去申请信号量,如果可以获取到信号量那么该线程就可以正常运行,如果获取资源失败那么就需要去等待。
当一个线程获取到信号量并且执行完成后必须去释放对应的信号量来通知其他线程进行工作,也就是说使用信号量不仅可以实现线程的互斥也可以实现线程间的同步。

信号量的操作:
①初始化
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数描述:
sem:用来标识那个信号量,是一个sem_t类型的值
pshared:pshared为0,表示信号量作用于同一进程下的线程间同步
value:信号量的初始值
返回值:
成功返回0, 失败返回错误码
②销毁信号量
int sem_destroy(sem_t *sem);
参数描述:
sem:用来标识是哪个信号量
返回值;
成功返回0,失败返回错误码
③获得资源操作(P操作)
int sem_wait(sem_t *sem);
函数说明:
wait操作,使信号量的值减1,如果已经是0,则该线程被挂起到等待队列。
参数描述:
sem:用来标识啥事那个信号量
返回值:
成功返回0, 失败返回错误码
int sem_trywait(sem_t *sem);
该函数与上面的函数作用一样,不过这个函数不会将线程挂起等待。
④释放资源操作(V操作)
int sem_post(sem_t *sem);
函数说明:
psot操作,使信号量的值加1,同时唤醒等待该信号量的线程。
参数描述:
sem:标识是哪个信号量
返回值:
成功返回0, 失败返回错误码

实例:
将环形队列设置为缓冲区,生产者每生产一个数据放入到缓冲区中,消费者每次从缓冲区中读出一个数据。
此时需要使用两个信号量,一个用来表示环形队列中空位置的数量,一个用来表示环形队列中数据的数量。

生产者只有等到有空位置时才能生产数据,消费者只有等到有数据时才能取到数据

[cpp]  view plain  copy
  1. #include<stdio.h>  
  2. #include<semaphore.h>  
  3. #include<pthread.h>  
  4.   
  5. //用数组模拟环形队列  
  6. int arr[8] = {0};  
  7. int i = 0;  
  8. int j = 0;  
  9. //设置信号量用来表示数组中的空位  
  10. sem_t blank;  
  11. //设置信号量用来表示数组中的数据  
  12. sem_t data;  
  13.   
  14. void *product(void *arg)  
  15. {  
  16.     while(1)  
  17.     {  
  18.     //生产者要生产必须要有空位,不然只能等待消费者取走数据之后才能生产  
  19.     sem_wait(&blank);  
  20.     arr[i%8] = rand()%123;  
  21.     printf("生产者生产完成:%d\n", arr[i%8]);  
  22.     i++;  
  23.     //当生产成功时,数据量+1  
  24.     sem_post(&data);  
  25.     sleep(i%3);  
  26.     }  
  27. }  
  28.   
  29. void *consumer(void *arg)  
  30. {  
  31.     while(1)  
  32.     {  
  33.     //消费者要消费必须有数据,不然只能等待生产者生产出数据之后才能取走  
  34.     sem_wait(&data);  
  35.     printf("消费者消费完成:%d\n", arr[j%8]);  
  36.     j++;  
  37.     //当消费成功时,空位量+1  
  38.     sem_post(&blank);  
  39.     sleep(j%5);  
  40.     }  
  41. }  
  42.   
  43. int main()  
  44. {  
  45.     //最开始,有8个空位  
  46.     sem_init(&blank, 0, 8);  
  47.     //最开始,还没有放入数据,数据为0个  
  48.     sem_init(&data, 0, 0);  
  49.     pthread_t thread1;  
  50.     pthread_t thread2;  
  51.   
  52.     pthread_create(&thread1, NULL, &product, NULL);  
  53.     pthread_create(&thread2, NULL, &consumer, NULL);  
  54.   
  55.     pthread_join(thread1, NULL);  
  56.     pthread_join(thread2, NULL);  
  57.   
  58.     sem_destroy(&blank);  
  59.     sem_destroy(&data);  
  60.     return 0;  
  61. }  

猜你喜欢

转载自blog.csdn.net/sunxiaopengsun/article/details/79914044