1. 程式人生 > >linux下的訊號量操作示例

linux下的訊號量操作示例

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <pthread.h>
#include <errno.h>
#include <vector>
#include <iostream>
using namespace std;
 
union semun {
        int              val;    /* Value for SETVAL */
        struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
        unsigned short  *array;  /* Array for GETALL, SETALL */
        struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                    (Linux specific) */
};
 
//工作執行緒函式
void * workproc(void * param)
{
        int sid = *(int *)param;  //訊號量ID
        pthread_t tid = pthread_self();  //執行緒ID
 
        cout <<"thread " <<tid <<"/t opt 1 is ok!" <<endl; //第一步操作執行完成
 
 //訊號量減1
        sembuf b;
        b.sem_num = 0;
        b.sem_op = -1;
        b.sem_flg = 0;
        int ret = semop(sid, &b, 1);
        if (ret != 0)
                return (void *)-1;
 
 //等待訊號量變成0
        cout <<"thread " <<tid <<"/t begin wait for all thread ok!" <<endl;
        b.sem_op = 0;
        ret = semop(sid, &b, 1);
        if (ret != 0)
                return (void *)-1;
        cout <<"thread " <<tid <<"/t end wait for all thread ok!" <<endl;
 
 //執行第二步操作
        cout <<"thread " <<tid <<"/t opt 2 is ok!" <<endl;
 
        return 0;
}
 
int main()
{
 //建立訊號量
        int sid = semget(IPC_PRIVATE, 1, IPC_CREAT|0660);
        if (sid == -1)
        {
                cout <<"create sem error!" <<endl;
                return -1;
        }
 
 //設定訊號量的初始值為5
        semun un;
        un.val = 5;
        int ret = semctl(sid, 0, SETVAL, un);
        if (ret == -1)
                return -1;
 
 //啟動一組工作執行緒
        vector<pthread_t> ids;  //儲存啟動的執行緒ID陣列
        pthread_t id;
        for (int i = 0; i < 5; ++i)
        {
                pthread_create(&id, NULL, workproc, &sid);
                ids.push_back(id);
        }
 
 //等待所有的工作執行緒結束
        int num = ids.size();
        for (int i = 0; i < num ; ++i)
        {
                pthread_join(ids[i], NULL);
        }
 
 //刪除訊號量
        semctl(sid, 1, IPC_RMID);
 
        return 1;
}