线程同步

  在之前的学习过程中,学习了进程同步。那么何谓同步?

  同步:多进程或者多线程访问临界资源时,必须进行同步控制。现在有一个临界资源,进程A向临界资源中写入数据,进程B从临界资源中读取数据。如果进程A中没有数据,那么进程B就无法读取,当然,在进程B读取数据的过程中,进程A就无法再向其中写入数据。这个过程就需要同步控制。多进程或者多线程的执行也并不是完全的并行运行,有的时候主线程的执行需要等待函数线程的某些条件的发生。

  之前学习进程间数据共享的时候,知道父子进程间除了共享文件描述符之外,全局数据、堆区数据和栈区数据都是不共享的。但是线程不一样,多线程之间除了栈区数据不共享之外,包括全局数据、堆区数据和文件相关数据都是共享的。

  多线程之间也有很多的临界资源,那么如何实现多线程的同步呢?今天就给大家介绍两种线程间的同步控制方式。

  一、信号量

     头文件:#include <semaphore.h>

     1、获取信号量

       函数原型:int sem_init(sem_t *sem,int shared,int value)    返回值:成功返回0,失败返回-1

       参数意义:sem:是一个sem_t类型的指针,指向信号量的对象

                         shared:能否在多进程中共享数据。linux中不支持,所以一般设置成0

                         value:信号量的初始值

      2、p操作

      函数原型:int sem_wait(sem_t *sem)

    3、v操作

      函数原型:int sem_post(sem_t *sem)

    4、删除

      函数原型:int sem_destroy(sem_t *sem)

    5、示例

      用信号量实现主线程循环获取用户输入,函数线程统计用户输入的字符个数(统计一次需要5秒)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <pthread.h>
#include <semaphore.h>

char buff[128]={0};
sem_t sem;
void  *char_count()//函数线程
{
	while(1)
	{
		sem_wait(&sem);//p操作
		if(strncmp(buff,"ok",2)==0)
		{
			break;
		}
		sleep(5);
		printf("count=%d\n",strlen(buff));

	}
	pthread_exit(NULL);

}
void  main()
{
	pthread_t id;
	int res=pthread_create(&id,NULL,char_count,NULL);
	assert(res==0);
	sem_init(&sem,0,0);//初始化

	printf("please input:");

	while(1)
	{
	
		fgets(buff,127,stdin);
		buff[strlen(buff)-1]=0;
		sem_post(&sem);//V操作

		if(strncmp(buff,"ok",2)==0)
		{
			exit(0);
		}
	}

	pthread_exit(NULL);
}
运行结果:

    当第一次输入的数据被读取之后,再接着输入,结果会很正确的被统计。但是如果第一次输入的数据尚未被统计,接着输入的话,结果就会出错

  

   当第一次输入的数据尚未被统计,再接着输入的话,结果就会出错。如下图所示。那么就无法真正地实现同步。说明用信号量解决多线程同步依旧有弊端,所以又有了另一种同步机制—互斥锁。

  

  二、互斥锁

    1、互斥锁的概念

       互斥锁就如生活中的锁一样,当上锁以后,无法在进去或者出来,只有等到解锁以后,才可以接着访问。互斥锁就是这样,使用它可以实现对临界资源的完全控制。当一个线程完成加锁操作以后,表示现在这个资源是该线程占有,其他的线程没有办法再进行加锁操作,也就意味着无法对临界资源实现访问,只有等到解锁操作以后。

    2、初始化操作

      函数原型:int pthread_mutex_init(pthread_mutex_t *mutex,pthread_mutex_t *attr)

    3、加锁操作

      函数原型:int pthread_mutex_lock(pthread_mutex_t *mutex)

    4、解锁操作

      函数原型:int pthread_mutex_unlock(pthread_mutex_t *mutex)

    5、释放 

      函数原型:int pthread_mutex_destroy(pthread_mutex_t *mutex)

    6、示例

      和上面信号量的例子一样,要求用互斥锁实现

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <pthread.h>
#include <semaphore.h>

char buff[128]={0};
pthread_mutex_t mutex;
void  *char_count()
{

	while(1)
	{
	    pthread_mutex_lock(&mutex);
		if(strncmp(buff,"ok",2)==0)
		{
			break;
		}

		printf("count=%d\n",strlen(buff));

		pthread_mutex_unlock(&mutex);
	    sleep(1);

	}
	pthread_exit(NULL);

}
void  main()
{
	pthread_t id;
	pthread_mutex_init(&mutex,NULL);//chu shi hua hu chi suo
	int res=pthread_create(&id,NULL,char_count,NULL);
	assert(res==0);
 
	printf("please input:\n");

	while(1)
	{
		pthread_mutex_lock(&mutex);
		fgets(buff,127,stdin);
		buff[strlen(buff)-1]=0;
		pthread_mutex_unlock(&mutex);

		if(strncmp(buff,"ok",2)==0)
		{
			exit(0);
		}
		sleep(1);
	}

	pthread_exit(NULL);
}

运行结果:

   

  






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值