Linux 多线程/进程同步

本文记录了Linux环境下多线程和多进程的同步问题,以生产者-消费者模型为例,探讨了使用POSIX信号量的实现方式。在多线程中,通过信号量控制生产阻塞和消费阻塞,以及使用互斥锁保护队列操作。而在多进程中,由于进程间不共享栈和堆,需将缓冲区改为保存完整产品信息,并采用共享内存实现信号量的同步。文章还提及了System V信号量作为另一种同步机制。
摘要由CSDN通过智能技术生成

Linux 多线程/进程同步

最近写作业学习了多线程/进程的经典同步问题,即生产者-消费者,在此做一些记录。主要是使用了semaphore.h中的POSIX信号量。

多线程

原理

多线程模拟一对一生产者-消费者,核心是三个:生产线程、消费线程、缓冲区。生产线程和消费线程同时执行,不考虑相互的直接影响,而是仅通过缓冲区的满和空控制生产阻塞和消费阻塞。生产线程向缓冲区放置产品,并减小其剩余容量,当剩余容量为0时生产暂停/阻塞,消费线程从缓冲区提取产品,并增大其剩余容量,当库存为0时消费暂停/阻塞。

方案

多线程实现生产者-消费者模型,要实现几个方面:

  1. 产品缓冲区,为了比较好的模拟实际情况,我使用了产品结构体指针循环队列,生产者使用calloc生产一个商品,使用push将其放入队列尾部,消费者使用pop从队列首部获得产品结构体指针,显示其gid,并使用free将其消耗(同时防止内存泄漏)。
  2. 控制生产阻塞和消费阻塞,使用两个sem_t信号量实现,其中g_sem_full控制生产阻塞,初始值为缓冲区容量,生产者生产之前对其sem_wait,消费者消费之后对其sem_post,g_sem_empty控制消费阻塞,初始值为0,消费者消费之前对其sem_wait,生产者生产之后对其sem_post。
  3. 三是实现对队列操作的互斥,使用pthread互斥锁pthread_mutex_t实现,在队列操作之前请求上锁,在完成操作之后解锁。
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <semaphore.h>
#include <sys/syscall.h>
#include <sys/types.h>

#define QUEUE_SIZE 4
#define COUNT 20

struct goods {
   
	int gid;
};

struct goods *queue[QUEUE_SIZE];
int head = 0;
int rear = 0;
int count = 0; // for using the full-size queue
int g_pcount = 0;
int g_ccount = 0;
pthread_mutex_t g_mutex;
sem_t g_sem_full;
sem_t g_sem_empty;

bool empty();
bool full();
int push(struct goods *);
struct goods *pop();
void *provider(void *);
void *consumer(void *);

int main()
{
   
	srand(getpid());
	sem_init(&g_sem_full, 0, QUEUE_SIZE);
	sem_init(&g_sem_empty, 0, 0);
	pthread_mutex_init(&g_mutex, NULL);
	pthread_t p1;
	pthread_t c1;
	pthread_create(&p1, NULL, provider, NULL);
	pthread_create(&c1, NULL, consumer, NULL);
	pthread_join(p1, NULL);
	pthread_join(c1, NULL);
	pthread_mutex_destroy(&g_mutex);
	sem_destroy(&g_sem_full);
	sem_destroy(&g_sem_empty);
}

bool empty()
{
   
	if (count == 0)
		return true;
	return false;
}

bool full()
{
   
	if (count == QUEUE_SIZE)
		return true;
	return false;
}

int push(struct goods *item)
{
   
	if (full())
		return -1;
	queue[rear] = item;
	rear = (rear+1) % QUEUE_SIZE;
	count++;
	return rear;
}

struct goods *pop()
{
   
	if (empty())
		return NULL;
	int temp = head;
	head = (head+1) 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值