互斥量+条件变量实现 信号量

概念

1.互斥量, 也就是互斥锁。互斥锁保证共享数据操作的完整性。每个对象都对应于一个可称为" 互斥锁" 的标记,这个标记用来保证在任一时刻,只能有一个线程访问该对象,但互斥锁有不足的地方,所以出现了条件变量

2…条件变量(semaphore), 条件变量不是锁 。条件变量是用来等待线程而不是上锁的,条件变量通常和互斥锁一起使用。条件变量之所以要和互斥锁一起使用,主要是因为互斥锁的一个明显的特点就是它只有两种状态:锁定和非锁定,而条件变量可以通过允许线程阻塞和等待另一个线程发送信号来弥补互斥锁的不足,所以互斥锁和条件变量通常一起使用。
3.信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。

1.互斥量和信号量

我们可以简单地把这个互斥量理解成一个bool类型
可以把信号量理解成一个int类型

2.

以前写过一个程序,用201个线程实现多线程求一段区间内的质数
现在给定一定数目的线程资源,来求取一段区间内的质数

条件变量 + 互斥量 实现信号量
信号量只要满足需求 就可以使用
参考哲学家就餐问题

#ifndef __MYSEM_H__
#define __MYSEM_H__

typedef void mysem_t ;

mysem_t * mysem_init(int value);
int mysem_add(mysem_t *, int value);
int mysem_sub(mysem_t *, int value);
int mysem_destroy(mysem_t *);


#endif
struct mysem_t
{
    
    
        int value;
        pthread_mutex_t mut;
        pthread_cond_t cond;  
};

//初始化
mysem_t * mysem_init(int value)
{
    
    
        struct mysem_t *me;

        me = malloc(sizeof(*me));
        if(NULL == me)
                return NULL;

        me->value = value;
        pthread_mutex_init(&me->mut, NULL);
        pthread_cond_init(&me->cond, NULL);

        return me;
}


int mysem_add(mysem_t *ptr, int value)
{
    
    
        struct mysem_t *me = ptr;


		//归还信号量 并发出通知
        pthread_mutex_lock(&me->mut);
        me->value += value;
        pthread_cond_broadcast(&me->cond);


        pthread_mutex_unlock(&me->mut);

        return value;



}

int mysem_sub(mysem_t *ptr, int value)
{
    
    

        struct mysem_t *me = ptr;
		//获取所需信号量
        pthread_mutex_lock(&me->mut);
        while(me->value < value)
        {
    
    
        		//等待事件发生
                pthread_cond_wait(&me->cond, &me->mut);
        }

        me->value -= value;

        pthread_mutex_unlock(&me->mut);

        return value;
}



int mysem_destroy(mysem_t * ptr)
{
    
    
        struct mysem_t *me = ptr;



        pthread_mutex_destroy(&me->mut);
        pthread_cond_destroy(&me->cond);

        free(me);

        return 0;
}
#define LEFT 30000000
#define RIGHT 30000200
#define SIZE (RIGHT-LEFT+1)
#define N 4
//最大信号量

mysem_t *sem;


void * Fun(void *p)
{
    
    
   int nNum = (int )p;
   int Flag = 1;
   int j;



   for(j = 2; j < nNum/2; j++)
   {
    
    
           if(0 == nNum % j)
           {
    
    
                   Flag = 0;
           }
   }

   if(Flag)
   {
    
    
           printf("%d is a prime\n", nNum);
   }

	//对信号量的归还
   mysem_add(sem, 1);

   pthread_exit(NULL);
}

int main()
{
    
    
   pthread_t tid[SIZE];
   int i,err;
	
	//对信号量进行初始化
   sem = mysem_init(N);
   if(NULL == sem)
   {
    
    
           fprintf(stderr, "init()\n");
           exit(1);
   }



   for(i = LEFT ; i <= RIGHT; i++)
   {
    
    
   			//获取信号量
           mysem_sub(sem, 1);
			//获取完 才能创建线程
           err = pthread_create(tid+(i-LEFT), NULL, Fun, (void *)i);
           if(err)
           {
    
    
                   fprintf(stderr, "create()%s ", strerror(err));
                   exit(1);
           }

   }



   for(i = LEFT; i <= RIGHT; i++)
   {
    
    
           pthread_join(tid[i-LEFT], NULL);

   }

   mysem_destroy(sem);

   return 0;
}

猜你喜欢

转载自blog.csdn.net/ZZHinclude/article/details/119734534