前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【线程同步】信号量

【线程同步】信号量

作者头像
mindtechnist
发布2024-08-08 17:19:50
1280
发布2024-08-08 17:19:50
举报
文章被收录于专栏:机器和智能

1. 什么是信号量

信号量相当于进化版的互斥锁。由于互斥锁的粒度比较大,如果我们希望在多个线程间对某一对象的部分数据进行共享,使用互斥锁是没有办法实现的,只能将整个数据对象锁住。这样虽然达到了多线程操作共享数据时保证数据正确性的目的,却无形中导致线程的并发性下降,线程从并行执行变成了串行执行,与直接使用单进程无异。信号量是相对折衷的一种处理方式,既能保证同步,数据不混乱,又能提高线程并发。

可以这么理解,比如说现在有一个资源可以允许三个线程同时访问,如果用互斥量的话,当第一个线程获取互斥锁的时候,后面的线程都会阻塞,这就无法实现三个线程同时访问资源了,会大大降低资源的利用效率。如果使用信号量,那个给信号量一个初值,每有一个线程访问到资源,信号量就减一,当减到0的时候,说明已经满足最多同时访问的线程数量了,后面的线程就不能再访问资源了,会阻塞。

2. 信号量相关API

2.1 初始化一个信号量

  • 头文件及函数原型
代码语言:javascript
复制
#include <semaphore.h>

int sem_init(sem_t *sem, int pshared, unsigned int value);

Link with -lrt or -pthread.
  • 函数描述 sem_init() initializes the unnamed semaphore at the address pointed to by sem. The value argument specifies the initial value for the semaphore.
  • 函数参数
    • sem:传输参数,代表信号量,不能小于0。sem_t信号量数据类型,是一个结构体,可以简单理解为类似于文件描述符的东西。sem_t数据类型的实现是对用户隐藏的,所以在后面的++和--操作都是只能通过函数sem_wait和sem_post来实现。信号量的初值决定了占用信号量的线程的个数。
    • pshared:
      • 0:用于线程间
      • 非0:用于进程间
    • value:指定信号量初值
  • 函数返回值 sem_init() returns 0 on success; on error, -1 is returned, and errno is set to indicate the error.

2.2 销毁一个信号量

  • 头文件及函数原型
代码语言:javascript
复制
#include <semaphore.h>

int sem_destroy(sem_t *sem);

Link with -lrt or -pthread.
  • 函数描述 sem_destroy() destroys the unnamed semaphore at the address pointed to by sem.
  • 函数参数
    • sem
  • 函数返回值 sem_destroy() returns 0 on success; on error, -1 is returned, and errno is set to indicate the error.

2.3 申请一个信号量(申请成功value--)

  • 头文件及函数原型
代码语言:javascript
复制
#include <semaphore.h>

/*--操作*/
int sem_wait(sem_t *sem);

int sem_trywait(sem_t *sem);

int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);

Link with -lrt or -pthread.
  • 函数描述
    • sem_wait() decrements (locks) the semaphore pointed to by sem. 信号量大于0,则信号量--,信号量等于0,则线程阻塞。
    • sem_trywait() is the same as sem_wait(), except that if the decrement can not be immediately performed, then call returns an error (errno set to EAGAIN) instead of blocking.
    • sem_timedwait() is the same as sem_wait(), except that abs_timeout specifies a limit on the amount of time that the call should block if the decrement cannot be immediately performed.
  • 函数参数
    • sem
  • 函数返回值 All of these functions return 0 on success; on error, the value of the semaphore is left unchanged, -1 is returned, and errno is set to indicate the error.

2.4 释放信号量(value++)

  • 头文件及函数原型
代码语言:javascript
复制
#include <semaphore.h>

/*++操作*/
int sem_post(sem_t *sem);

Link with -lrt or -pthread.
  • 函数描述 sem_post() increments (unlocks) the semaphore pointed to by sem. 信号量++,同时唤醒阻塞在信号量上的线程。
  • 函数参数
    • sem
  • 函数返回值 sem_post() returns 0 on success; on error, the value of the semaphore is left unchanged, -1 is returned, and errno is set to indicate the error.

3. 信号量实现生产者消费者模型

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

#define MAX 6
sem_t blank, ful;
int vector[MAX];
int gdata = 100;

void* producer_th(void* arg)
{
    int i = 0;
    while(1)
    {
        sem_wait(&blank);
        printf("thread: %s, tid: %lu, data: %d\n", __FUNCTION__,\
               pthread_self(), gdata);
        vector[(i++)%MAX] = gdata++;
        sem_post(&ful);
        sleep(rand()%3);
    }
    return NULL;
}

void* consumer_th(void* arg)
{
    int i = 0;
    int num = 0;
    while(1)
    {
        sem_wait(&ful);
        num = vector[(i++) % MAX];
        printf("thread: %s, tid: %lu, data: %d\n", __FUNCTION__,\
               pthread_self(), num);
        sem_post(&blank);
        sleep(rand()%3);
    }
    return NULL;
}

int main(int argc, char* argv[])
{
    sem_init(&blank, 0, MAX); /*生产者*/
    sem_init(&ful, 0, 0); /*消费者*/
    pthread_t t1, t2;
    pthread_create(&t1, NULL, producer_th, NULL);
    pthread_create(&t2, NULL, consumer_th, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    sem_destroy(&blank);
    sem_destroy(&ful);
    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器和智能 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 什么是信号量
  • 2. 信号量相关API
    • 2.1 初始化一个信号量
      • 2.2 销毁一个信号量
        • 2.3 申请一个信号量(申请成功value--)
          • 2.4 释放信号量(value++)
          • 3. 信号量实现生产者消费者模型
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档