信号量Semaphore的用法

信号量(Semaphore)

 

信号量和互斥锁(mutex)的区别:互斥锁只允许一个线程进入临界区,而信号量允许多个线程同时进入临界区。

不多做解释,要使用信号量同步,需要包含头文件semaphore.h。

主要用到的函数:

int sem_init(sem_t *sem, int pshared, unsigned int value);
其中sem是要初始化的信号量,pshared表示此信号量是在进程间共享还是线程间共享,
value是信号量的初始值。

int sem_destroy(sem_t *sem);,其中sem是要销毁的信号量。
只有用sem_init初始化的信号量才能用sem_destroy销毁。

int sem_wait(sem_t *sem);等待信号量,如果信号量的值大于0,将信号量的值减1,立即返回。
如果信号量的值为0,则线程阻塞。相当于P操作。成功返回0,失败返回-1。

int sem_post(sem_t *sem); 释放信号量,让信号量的值加1。相当于V操作。

int sem_getvalue(sem_t *sem, int *sval);
取回信号量sem的当前值,把该值保存到sval中。
若有1个或更多的线程或进程调用sem_wait阻塞在该信号量上,该函数返回两种值:
1) 返回0
2) 返回阻塞在该信号量上的进程或线程数目
linux采用返回的第一种策略。

 

如果我們現在有兩個執行緒,分別負責一份工作的前半段與後半段,也就是說第一個執行緒會把它處理好的資料,發包給第二個執行緒繼續處理,而兩個執行緒的處理速度有可能不同,這種狀況我們就可以使用旗標(Semaphore)的方式來串接。

旗標本身就是一個計數器,也就是紀錄目前尚未處理的工作數量,我們可以使用 sem_wait 來判斷是否有尚未處理的工作,當工作數量大於 0 時,sem_wait 就會讓執行緒進入處理,並且把工作數量遞減 1,而如果工作數量為 0 的時候,則會讓執行緒等待,直到有新的工作來臨時,才讓執行緒進入。

另外在產生工作的執行緒中,可以使用 sem_post 放入新的工作(也就讓將計數器遞增 1),這樣就可以將多個執行緒串接起來處理大型的工作流程。

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>

sem_t semaphore; // 旗標
int counter = 0;

// 子執行緒函數
void* child() {
  for(int i = 0;i < 5;++i) {
    sem_wait(&semaphore); // 等待工作
    printf("Counter = %d\n", ++counter);
    sleep(1);
  }
  pthread_exit(NULL);
}

// 主程式
int main(void) {

  // 初始化旗標,僅用於本行程,初始值為 0
  sem_init(&semaphore, 0, 0);

  pthread_t t;
  pthread_create(&t, NULL, child, NULL);

  // 送出兩個工作
  printf("Post 2 jobs.\n");
  sem_post(&semaphore);
  sem_post(&semaphore);
  sleep(4);

  // 送出三個工作
  printf("Post 3 jobs.\n");
  sem_post(&semaphore);
  sem_post(&semaphore);
  sem_post(&semaphore);

  pthread_join(t, NULL);
  sem_destroy(&semaphore);

  return 0;
}

执行结果:

Post 2 jobs.
Counter = 1
Counter = 2
Post 3 jobs.
Counter = 3
Counter = 4
Counter = 5

在這個程式中,主執行緒負責派送工作,工作有時候多、有時候少,而子執行緒則是以每秒處理一個工作的速度,消化接收到的工作。

旗標在使用前要先以 sem_init 初始化,其第二個參數是指定是否要讓其他的行程(process)共用旗標,這裡我們是單一行程、多執行緒的程式,所以第二個參數設定為 0 即可;第三個參數則是設定旗標的初始值

旗標本身只是紀錄工作的數量,並且控制執行緒的執行,並沒有負責資料的配送,通常我們可以自己實做一個資料佇列(queue),配合旗標來計算索引,讓子執行緒從佇列中取得資料進行處理。

 

参考:https://blog.gtwang.org/programming/pthread-multithreading-programming-in-c-tutorial/

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值