线程同步问题

多进程之间访问临界资源需要进行同步控制,那么线程也是一样的,多线程访问临界资源时也同样需要进行同步控制。多进程或者多线程的执行并不完全是绝对的并行运行,有可能主线程需要等待函数线程的某些条件的发生。

进程间的全局变量,栈区,堆区的数据都不共享,只有文件描述符是共享的,而线程之间的全局变量,堆区,文件描述符都是共享的。

多线程之间同步控制方式:

(1)信号量

获取:

        int sem_init(sem_t *sem,int shared,int value);

            sem:是一个sem_t类型指针,指向信号量对象。

            shared:是否能在多进程间共享,Linux不支持,设为0。

            value:信号量初始值

             返回值:0--成功  -1--失败

P操作:

       int sem_wait(sem_t *sem) ;//阻塞运行

V操作:

        int sem_post(sem_t *sem);
删除:

        int sem_destroy(sem_t *sem);

例题:主线程循环获取用户输入,函数线程统计用户输入的字符个数

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

pthread_mutex_t mutex;
char buff[128]={0};

void *fun()
{
	while(1)
	{
		pthread_mutex_lock(&mutex);
		if(strncmp(buff,"end",3)==0)
		{
			break;
		}
		printf("count==%d\n",strlen(buff));

		pthread_mutex_unlock(&mutex);
		sleep(1);
	}
}

void main()
{
	pthread_t id;
	pthread_mutex_init(&mutex,NULL);
	int res=pthread_create(&id,NULL,fun,0);
	
	assert(res==0);
	char *q=NULL;

	while(1)
	{
		pthread_mutex_lock(&mutex);
		printf("please input:\n");
		fgets(buff,127,stdin);
		buff[strlen(buff)-1]=0;
		
		pthread_mutex_unlock(&mutex);
		if(strncmp(buff,"end",3)==0)
		{
			break;
		}
		sleep(1);
	}
	pthread_exit(NULL);
}
(2)互斥锁

什么是互斥锁?

完全控制临界资源,如果一个线程完成加锁操作,则其他线程无论如何都无法再完成加锁,也就无法对临界资源进行访问。

初始化:

      int pthread_mutex_init(pthread_mutex_t *mutex,pthread_mutex_attr_t *attr);

加锁:

       int pthread_mutex_lock(pthread_mutex_t *mutex);//阻塞运行

       int pthread_mutex_trylock(pthread_mutex_t *mutex);//非阻塞运行版本

解锁:

      int pthread_mutex_unlcok(pthread_mutex_t *mutex);

释放:

      int pthread_mutex_destroy(pthread_mutex_t *mutex);

(3)条件变量

2、线程安全

   有些库函数会使用线程间共享的数据,如果没有同步控制,线程操作就是不安全的,所以,我们使用这样一些函数时,就必须使用其安全版本-->可重入函数


3、线程中fork的使用,锁的变化

在线程中调用fork函数,子进程只会启用fork函数的那条线程,其他线程不会启用。

子进程会继承其父进程的锁以及锁的状态,但是父子进程用的不是同一把锁,父进程解锁并不会影响到子进程的锁,所以子进程有可能死锁!

pthread_atfork(void(*prepare)(void),void (*parent)(void),void (*child)(void));

指定在fork调用之后,创建子进程之前,调用prepare函数,获取所有的锁,然后创建子进程,子进程创建以后,父进程环境中调用parent,解开所有锁,子进程环境中调用child,解开所有锁,然后fork函数再返回。这样保证了fork之后,子进程拿到的锁都是解锁状态,避免死锁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值