十六、条件变量和信号量

1、条件变量

  条件变量
  阻塞线程
  不是什么时候都能阻塞线程
链表头节点
Node*head = NULL;
while(head == NULL)
{
//我们想让代码在这个位置阻塞
//等待链表中有了节点之后再继续向下运行
//使用到了后面要讲的条件变量‐阻塞线程
}
//链表不为空的处理代码

  条件变量是锁吗?

        不是锁,但是条件变量能够阻塞线程

        使用条件变量+互斥量

            互斥量:保护一块共享数据

            条件变量:引起阻塞

                生产者和消费者模型

  条件变量的两个动作

      条件不满足,阻塞线程

      当条件满足,通知阻塞的线程开始工作

  条件变量的类型

  pthread_cond_t cond ;

  conditon 条件

  主要函数:

     初始化一个条件变量

         pthread_cond_init(pthread_cond_t * restrict cond,

         const pthread_condattr_t * restrict attr

         );

     销毁一个条件变量

         pthread_cond_destroy(pthread_cond_t * cond);

    阻塞等待一个条件变量

         pthread_cond_wait(

         pthread_cond_t *restrict cond,

         pthread_mutex_t * restrict mutex

         );

        阻塞线程

        将已经上锁的mutex解锁

        该函数解除阻塞,对互斥锁加锁

    限时等待一个条件变量

          pthread_cond_timedwait(

          pthread_cond_t * restrict cond,

          pthread_mutex_t * restrict mutex,

          const struct timespec * restrict abstime

           );

    唤醒至少一个阻塞在条件变量上的线程

         pthread_cond_signal(pthread_cond_t* cond);

    唤醒全部阻塞在条件变量上的线程

         pthread_cond_broadcast(pthread_cond_t * cond);

  练习

    使用条件变量实现生产者,消费者模型

#include
#include
#include
#include
typedef struct node
{
	int data;
	struct node* next;
}Node;
Node* head=NULL;
pthread_mutex_t mutex;
pthread_cond_t cond;
void* produce(void* arg)
{
   while(1)
   {
	   Node* pnew;
	   pnew=(Node*)malloc(sizeof(Node));
	   pthread_mutex_lock(&mutex);
	   pnew->data=random()%1000;
	   pnew->next=head;
	   head=pnew;
	   printf("produce:%ld,%d\n",pthread_self(),pnew->data);
	   pthread_mutex_unlock(&mutex);
	   pthread_cond_signal(&cond);
	   sleep(random()%3);
   }
   return NULL;
}
void* custmer(void* arg)
{
	while(1)
	{
		pthread_mutex_lock(&mutex);
		if(head==NULL)
		{
		pthread_cond_wait(&cond,&mutex);
				}
		Node* pdel=head;
		head=head->next;
		printf("custmer:%ld,%d\n",pthread_self(),pdel->data);
		free(pdel);
		pthread_mutex_unlock(&mutex);
	}
	return NULL;
}
int main()
{
	pthread_mutex_init(&mutex,NULL);
	pthread_cond_init(&cond,NULL);
	pthread_t p1,p2;
	pthread_create(&p1,NULL,produce,NULL);
	pthread_create(&p2,NULL,custmer,NULL);
	pthread_join(p1,NULL);
	pthread_join(p2,NULL);
	pthread_mutex_destroy(&mutex);
	pthread_cond_destroy(&cond);
	return 0;
}

运行结果:

十六、条件变量和信号量_第1张图片

2、信号量

头文件-semaphore.h

信号量类型

  sem_t sem;

  加强版的互斥锁

主要函数

  初始化信号量

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

     0-线程同步1-进程同步

     value-最多有几个线程操作共享数据

  销毁信号量

     sem_destroy(sem_t *sem);

  加锁

     sem_wait(sem_t *sem);

          调用一次相当于对sem做了一次 -- 操作

          如果sem值为0,线程会阻塞

  尝试加锁

          sem_trywait(sem_t *sem);

          sem == 0;加锁失败,不阻塞,直接发牛

  限时尝试加锁

          sem_timewait(sem_t *sem,xxxx);

  解锁++

    sem_post(sem_t *sem);

         对sem做了++ 操作

练习

使用信号量实现生产者,消费者模型。

#include
#include
#include
#include
#include
typedef struct node
{
	int data;
	struct node* next;
}Node;
Node* head=NULL;
pthread_mutex_t mutex;
sem_t produce_sem,custmer_sem;
void* produce(void* arg)
{
   while(1)
   {
	   sem_wait(&produce_sem);
	   Node* pnew;
	   pnew=(Node*)malloc(sizeof(Node));
	   pnew->data=random()%1000;
	   pnew->next=head;
	   head=pnew;
	   printf("produce:%ld,%d\n",pthread_self(),pnew->data);
	   sem_post(&custmer_sem);
	   sleep(random()%3);
   }
   return NULL;
}
void* custmer(void* arg)
{
	while(1)
	{
		sem_wait(&custmer_sem);
		Node* pdel=head;
		head=head->next;
		printf("custmer:%ld,%d\n",pthread_self(),pdel->data);
		free(pdel);
		sem_post(&produce_sem);
	}
	return NULL;
}
int main()
{
        sem_init(&produce_sem,0,4);
	sem_init(&custmer_sem,0,0);
	pthread_t p1,p2;
	pthread_create(&p1,NULL,produce,NULL);
	pthread_create(&p2,NULL,custmer,NULL);
	pthread_join(p1,NULL);
	pthread_join(p2,NULL);
	sem_destroy(&produce_sem);
	sem_destroy(&custmer_sem);
	return 0;
}

运行结果:

十六、条件变量和信号量_第2张图片

你可能感兴趣的:(Linus,linux,c语言)