linux环境变成-线程同步【信号量】

一.信号量

进化版的互斥锁(1---->N)

由于互斥锁的粒度比较大,如果我们希望多个线程间对某个对象的部分数据进行共享【类似于行锁,拥有部分是不一样的】,使用互斥锁是没有办法实现的,只能讲整个对象锁住,这样虽然保证了多个线程操作同一个共享资源数据的正确性,但同时也降低了 线程的并发程度。线程从并行执行变为串行执行,与直接用单进程操作该数据速度还要慢些,为什么呢? 因为锁 也是一种资源,上锁和 解锁 也是有开销的。

信号量是一种相对折中的方式,即能保证同步,数据不紊乱,也能保证线程/进程的并发性

二.信号量的主要应用函数

  • sem _init,函数
  • sem_destroy函数
  • sem_wait函数
  • sem_trywait函数
  • sem_timedwait函数
  • sem_post函数

以上6个函数的返回值都是:成功返回0,失败返回-1,同时设置errno。(注意,它们没有pthread前缀==>进程也可以用)
sem_t类型,本质仍是结构体。但应用期间可简单看作为整数,忽略实现细节(类似于使用文件描述符)
sem_t sem:规定信号量sem不能<0。头文件<semaphore.h>
 

三.信号量基本操作:

sem -wait:            1.信号量大于0,则信号量--(类比 pthread_mutex_lock)   2.信号量等于0,造成线程阻塞
l
对应
l
sem_post:将信号量++,同时唤醒阻塞在信号量上的线程(类比pthread_mutex_unlock)但,由于sem_t的实现对用户隐藏,所以所谓的++、--操作只能通过函数来实现,而不能直接++、--符号。信号量的初值,决定了占用信号量的线程的个数。

四.信号量函数详解

1.sem_ init函数初始化一个信号量
int sem_init(sem_t*sem, int pshared,unsigned int value);

  • 参1: sem信号量
  • 参2: pshared,取0用于线程间;取非0(一般为1)用于进程间
  • 参3: value指定信号量初值

2.sem_destroy函数销毁一个信号量
int sem_destroy(sem_t*sem);

 

3.sem wait函数给信号量加锁--
int sem _wait(sem_ t *sem);

4.sem post函数给信号量解锁++
int sem post(sem _t *sem);

 

五.代码Demo【生产者 消费者 信号量模型】

#include <iostream>
#include <semaphore.h>
#include <unistd.h>
#include <time.h>


using namespace std;

#define THREAD_NUM 8

sem_t sem_blank, sem_star;
int queue[THREAD_NUM];

void*
prod_func(void* arg)
{
	int i = THREAD_NUM;
	int index = 0;
	while(i--){
		sem_wait(&sem_blank);
		queue[index] = rand()%THREAD_NUM + 1;
		printf("-----productor----- %d \n", queue[index]);
		sem_post(&sem_star);
		index = (index+1) % THREAD_NUM;
		sleep(rand()%2+1);
	}
	pthread_exit(NULL);
}

void*
cons_func(void* arg)
{
	int i = THREAD_NUM;
	int index = 0;
	while(i--){
		sem_wait(&sem_star);
		printf("-----consumer----- %d \n", queue[index]);
		queue[index] = 0;
		sem_post(&sem_blank);
		index = (index+1) % THREAD_NUM;
		sleep(rand()%3);
	}
	
	pthread_exit(NULL);
}



int
main(int argc, char*argv[])
{
	pthread_t prod_tid, cons_tid;
	sem_init(&sem_blank, 0, THREAD_NUM);
	sem_init(&sem_star, 0, 0);
	srand(time(NULL));
	
	pthread_create(&prod_tid, NULL, prod_func, NULL);
	pthread_create(&cons_tid, NULL, cons_func, NULL);

	pthread_join(prod_tid, NULL);
	pthread_join(cons_tid, NULL);
		
	sem_destroy(&sem_blank);
	sem_destroy(&sem_star);
	pthread_exit(NULL);
}

原理图

猜你喜欢

转载自blog.csdn.net/qq_44065088/article/details/109219495
今日推荐