Linux线程之信号量(semaphore)

Linux信号量

  • 1. 头文件
  • 2. 类型
    • 2.1. 类型值
  • 3. 接口
    • 3.1. 信号量接口
      • 3.1.1 动态初始化资源
      • 3.1.2. 动态释放资源
      • 3.1.3. 信号量锁定
      • 3.1.4. 带超时时间的信号量锁定
      • 3.1.5. 不阻塞信号量锁定
      • 3.1.6. 信号量解锁
      • 3.1.6. 获取当前信号量的值
  • 4. 示例
    • 4.1. 信号量示例

1. 头文件

#include

2. 类型

2.1. 类型值

//信号量类型
sem_t   semTest;

3. 接口

3.1. 信号量接口

3.1.1 动态初始化资源

/*
 * 函数名称:sem_init
 * 功能:动态初始化信号量资源
 * 参数:
 * 		__sem: 指向待初始化的信号量对象地址
 * 		__pshared:0表示信号量是在同一个进程中的不同线程间进行同步,非0表示信号量共享在不同的进程中。
 * 		__value:表示初始化可共享的线程的数量
 * 返回值:0--成功,-1-失败,并会把errno设置为具体的错误类型
*/
int sem_init (sem_t *__sem, int __pshared, unsigned int __value);

3.1.2. 动态释放资源

/*
 * 函数名称:sem_destroy
 * 功能:动态释放信号量资源
 * 参数:
 * 		__sem: 指向需要释放的信号量对象地址
 * 返回值:0--成功,-1--失败,并会把errno设置为具体的错误类型
*/
int sem_destroy (sem_t *__sem);

3.1.3. 信号量锁定

/*
 * 函数名称:sem_wait
 * 功能:当信号量的值大于0时则减1直接返回,当信号量的值小于等于0则阻塞当前线程直到信号量的值大于0时,执行减1后返回
 * 参数:
 * 		__sem: 指向需要等待的信号量对象地址
 * 返回值:0--成功,-1--失败,并会把errno设置为具体的错误类型
*/
int sem_wait (sem_t *__sem);

3.1.4. 带超时时间的信号量锁定

//时间结构体
struct timespec
{
	__time_t tv_sec;   //秒
	long int tv_nsec;	//纳秒
};
/*
 * 函数名称:sem_timewait
 * 功能:当信号量的值大于0时则减1直接返回,当信号量的值小于等于0则阻塞当前线程直到达到指定的超时时间后返回,或者为达到超时时间信号量的值大于0时,执行减1后返回
 * 参数:
 * 		__sem: 指向需要等待的信号量对象地址
 * 		__abstime:设置的相对于UTC时间的绝对超时时间,需要先获取当前时间然后在加上超时时间
 * 返回值:0--成功,-1--失败,并会把errno设置为具体的错误类型
*/
int sem_timedwait (sem_t *__sem, const struct timespec *__abstime); 

3.1.5. 不阻塞信号量锁定

/*
 * 函数名称:sem_trywait
 * 功能:测试信号量是否可以减1,如果不能则直接返回,并返回错误码
 * 参数:
 * 		__sem: 指向需要减1的信号量对象地址
 * 返回值:0--成功,-1--失败,并会把errno设置为具体的错误类型
*/
int sem_trywait (sem_t *__sem);

3.1.6. 信号量解锁

/*
 * 函数名称:sem_post
 * 功能:对信号量进行加1操作,即解锁
 * 参数:
 * 		__sem: 指向信号量对象地址
 * 返回值:0--成功,-1--失败,并会把errno设置为具体的错误类型
*/
int sem_post (sem_t *__sem);

3.1.6. 获取当前信号量的值

/*
 * 函数名称:sem_getvalue
 * 功能:获取当前信号量的值
 * 参数:
 * 		__sem: 指向信号量对象地址
 * 		__sval:指向当前信号量值的存储地址
 * 返回值:0--成功,-1--失败,并会把errno设置为具体的错误类型
*/
int sem_getvalue (sem_t * __sem, int * __sval);

4. 示例

4.1. 信号量示例

##include <iostream>
#include 
#include 
#include 

//全局信号量定义
sem_t g_sem;

static void* semWaitThread(void *arg)
{
    std::cout << "enter semWaitThread " << pthread_self() << " ." << std::endl;
    
    sem_wait(&g_sem);
    
    //获取当前信号量值
    int iValue = 0;
    sem_getvalue(&g_sem, &iValue);
    std::cout << "thread id is " << pthread_self() << ", sem value is " << iValue << std::endl;
    std::cout << "semWaitThread continue " << pthread_self() << " ." << std::endl;

    return nullptr;
}

static void* semPostThread(void *arg)
{
    std::cout << "enter semPostThread " << pthread_self() << " ." << std::endl;
    
    sem_post(&g_sem);
    
    //获取当前信号量值
    int iValue = 0;
    sem_getvalue(&g_sem, &iValue);
    std::cout << "thread id is " << pthread_self() << ", sem value is " << iValue << std::endl;
    std::cout << "semPostThread continue " << pthread_self() << " ." << std::endl;
    return nullptr;
}

int main()
{
    //信号量初始化
    sem_init(&g_sem, 0, 2);

    //创建3个信号量阻塞线程
    pthread_t semWaitThreadId[3];
    for (int i = 0; i < 3; i++)
    {
        int iValue = i+1;
        pthread_create(&semWaitThreadId[i], nullptr, semWaitThread, nullptr);
        pthread_detach(semWaitThreadId[i]);
        sleep(1);
    }
    
    sleep(3);
    //创建3个信号量释放线程
    pthread_t semPostThreadId[3];
    for (int i = 0; i < 3; i++)
    {
        int iValue = i+1;
        pthread_create(&semPostThreadId[i], nullptr, semPostThread, nullptr);
        pthread_detach(semPostThreadId[i]);
        sleep(1);
    }

    //信号量销毁
    sem_destroy(&g_sem);

    return 0;
}
enter semWaitThread 140258284926528 .
thread id is 140258284926528, sem value is 1
semWaitThread continue 140258284926528 .
enter semWaitThread 140258284926528 .
thread id is 140258284926528, sem value is 0
semWaitThread continue 140258284926528 .
enter semWaitThread 140258284926528 . 因为信号量为2所以第三个线程会在此处阻塞。
enter semPostThread 140258276533824 . 此处有一个post操作信号量加1,后续被阻塞的线程获取信号量继续执行。
thread id is 140258276533824, sem value is 1 此时被阻塞的线程继续执行
semPostThread continue 140258276533824 .
thread id is 140258284926528, sem value is 0
semWaitThread continue 140258284926528 .
enter semPostThread 140258284926528 .
thread id is 140258284926528, sem value is 1
semPostThread continue 140258284926528 .
enter semPostThread 140258284926528 .
thread id is 140258284926528, sem value is 2
semPostThread continue 140258284926528 .

你可能感兴趣的:(Linux系统编程,linux)