信号量(实现线程的同步与互斥)

18 篇文章 0 订阅
9 篇文章 0 订阅

信号量:

功能: 实现线程间的同步与互斥
本质:一个计数器(做资源计数-判断当前是否能对临界资源进行操作)+等待+唤醒 +等待队列
    原理:
        互斥原理:只具有0或1计数时,就可以实现互斥,初始计数为1,1表示当前只有一个线程能获取资源;
                 获取资源之后-1,等操作完后+1,当计数为0时,其他线程进行等待(将PCB加入到等待队列)  
        同步原理:对程序逻辑进行控制(对临界资源合理操作控制);通过计数判断当前是否能够对临界资
                 源进行访问,不能操作(计数<=0),则等待;

相关接口

定义信号量变量

变量类型: sem_t       头文件: #include <semaphore.h> 

初始化信号量

 int sem_init(sem_t *sem, int pshared, unsigned int value);
 sem: 定义的信号变量
 pshared:0表示线程中的信号, 非零表示进程间的信号量
 value: 信号量初始值

销毁信号量

 int sem_destroy(sem_t* sem);

等待信号量

 功能:等待信号量,会将信号量的值减1
 int sem_wait(sem_t *sem); 

发布信号量

 功能:发布信号量,表示资源使用完毕,可以归还资源了。将信号量值加1。 
 int sem_post(sem_t *sem); 

通过信号量实现生产者消费者模型

过程: 生产者线程向仓库(一个环形队列)加入数据, 消费者线程在这个仓库中取出数据

封装模型类

具体代码如下:

#include <iostream>
#include <semaphore.h>
#include <pthread.h>
#include <vector>
#include <stdio.h>
using namespace std;
#define MAX_SOTR 5

class Sem_PC_test{
  private:
    sem_t _lock;  // 用于实现储存仓库的互斥
    sem_t _data; // 用于实现消费者线程仓库容量的计数
    sem_t _prod; // 用于实现生产者线程仓库容量的计数
    vector<int> _stor; // 定义一个仓库
    int _wirte; // 写的位置用于实现环形队列
    int _read; // 读的位置用于实现环形队列

  public:
    Sem_PC_test(const int cap = MAX_SOTR) 
      :_stor(cap)
      ,_wirte(0)
      ,_read(0)
    {
      sem_init(&_lock, 0, 1);   // 初始化锁
      sem_init(&_data, 0, 0);
      sem_init(&_prod, 0, MAX_SOTR);
    }

    ~Sem_PC_test()
    {
      sem_init(&_lock, 0, 1); 
      sem_init(&_data, 0, 0);
      sem_init(&_prod, 0, MAX_SOTR);
    }

    bool Push_data(const int& data)
    {
    sem_wait(&_prod); // 生产者线程获取信号值
    sem_wait(&_lock); // 加锁
    _stor[_wirte] = data; 	//写入数据
    _wirte = (_wirte+1)% MAX_SOTR; // 实现环形队列
    sem_post(&_lock); // 发布信号(开锁)
    sem_post(&_data);// 向消费者线程的条件变量发布信号
    return true;
    }

    bool Get_data(int& data)
    {
      sem_wait(&_data);
      sem_wait(&_lock);
      data = _stor[_read];
      _read = (_read+1)% MAX_SOTR;
      sem_post(&_lock);
      sem_post(&_prod); 
      return true;
    }
};
void* test_get(void* agr)
{
  int a;
  while(1)
  {
  Sem_PC_test* p = (Sem_PC_test*)agr;
  p->Get_data(a);
  printf("线程%lu,获取到值%d\n", pthread_self(), a);
  }
  return NULL;
}


void* test_push(void* agr)
{
  static int i = 0;
  while(1)
  {
  Sem_PC_test* p = (Sem_PC_test*)agr;
  p->Push_data(i);
  i++;
  }
  return NULL;
}
int main()
{
  pthread_t tid[4], PC[4];
  int i;
  Sem_PC_test data;
  
  for(i=0; i<4; i++)
  {
    pthread_create(&tid[i], NULL ,test_get , (void*)&data);
  }
  for(i=0; i<4; i++)
  {
    pthread_create(&PC[i], NULL , test_push, (void*)&data);
  }
  
  
  for(i=0; i<4; i++)
  {
    pthread_join(tid[i],NULL);
  }

  for(i=0; i<4; i++)
  {
    pthread_join(PC[i],NULL);
  }
  return 0;
}

 编译代码: g++ Sem_PC_test.cpp -o Sem_PC_test -lpthread

运行结果如下:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在并发编程中,同步互斥是两个重要的概念。信号量机制是一种用于实现同步互斥的机制。下面分别从同步互斥两个角度来分析信号量机制。 1. 同步 同步是指协调多个进程或线程的执行顺序,以避免竞态条件和死锁等问题。在信号量机制中,同步可以通过信号量的 P 操作和 V 操作实现。 当进程或线程需要访问一个共享资源时,它首先执行 P 操作,该操作会将信号量的值减 1。如果信号量的值已经为 0,则执行 P 操作的进程或线程会被阻塞,直到信号量的值变为大于 0 为止。这样,就可以保证每个进程或线程都能按照一定的顺序访问共享资源,从而实现同步。 2. 互斥 互斥是指在多个进程或线程访问共享资源时,只有一个进程或线程能够访问该资源,以避免数据竞争问题。在信号量机制中,互斥可以通过二元信号量(也称为二元锁)实现。 二元信号量的值只有 0 和 1 两种状态。当进程或线程需要访问共享资源时,它执行 P 操作,如果信号量的值为 1,则将其值减 1 并继续执行。如果信号量的值为 0,则执行 P 操作的进程或线程会被阻塞,直到其他进程或线程释放该资源并执行 V 操作,将信号量的值加 1 为止。这样,就可以保证同时只有一个进程或线程访问共享资源,从而实现互斥。 总之,信号量机制是一种非常重要的同步互斥机制,在并发编程中广泛应用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值