linux-线程\进程同步

线程\进程同步

线程同步

1>同步概念:协同步调,按预定先后顺序访问共享数据.
2>访问共享数据的所有线程都硬加锁.(不加锁就可以直接访问)
在这里插入图片描述

1.互斥量(互斥锁)(mutex)

1>访问共享资源后应立即解锁(保证加锁粒度最小)
2>死锁问题:1:对同一个锁加锁两次,第二次就会阻塞等待(解决办法:细心);2:两个线程同时去加锁对方已经加锁的锁时,双方均会阻塞等待.使用trylock一样(解决办法:当线程不能索取全部锁时,主动放弃所有的锁让对方加锁完成访问后释放锁)3:震荡:哲学家吃饭问题,只需一个与其他的那口子的顺序不同即可
3>实现

 #include<stdio.h>
 #include<pthread.h>
 #include<unistd.h>
    /***********************互斥量的控制函数格式:pthread_mutex_xxx********************************
	*函数1:pthread_mutex_init() 
	*头文件:#include <pthread.h>
	*格式:int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
	*参数:pthread_mutex_t:结构体,用来定义一个锁(mutex:取值0(加锁)\1(解锁))e(*restrict作用:限制其他指针对mutex的地址进行修改,只能本指针完成)
	*参数:const pthread_mutexattr_t *restrict attr:默认值传入NULL;
	*作用:初始化一个锁(互斥量)
	********************************************************
	*函数2:pthread_mutex_destroy() 
	*头文件:#include <pthread.h>
	*格式: int pthread_mutex_destroy(pthread_mutex_t *mutex);//pthread_mutex_t *mutex:传入参数,传入锁
	*作用:destroy  a mutex(互斥量)//与初始化对应
	*返回值:If  successful,  the  pthread_mutex_destroy()  and pthread_mutex_init() functions shall return  zero;  otherwise,  an  error  number  shall  be
    *returned to indicate the error.
    ********************************************************
	*函数3-5:pthread_mutex_lock() \pthread_mutex_unlock()\pthread_mutex_trylock()
	*头文件:#include <pthread.h>
	*格式:  int pthread_mutex_lock(pthread_mutex_t *mutex);//作用:对线程进行阻塞加锁(如果加锁不成功,就会阻塞在此处),pthread_mutex_t *mutex:传入参数,传入锁
       		 int pthread_mutex_trylock(pthread_mutex_t *mutex);//作用:对线程加锁,非阻塞的方式(因此要采用轮询的方式);
       		 int pthread_mutex_unlock(pthread_mutex_t *mutex);//解锁
	*返回值:成功-0;错误-错误号;
	*****************************互斥量的控制函数格式:pthread_mutex_xxx***************************/
	pthread_mutex_t mutex;//1.定义锁要放在全局变量(子线程能访问)
	
	void * func(void* arg)
	{
		while(1)
		{
			pthread_mutex_lock(&mutex);//加锁
			printf("HELLO");
			sleep(1);
			printf("WORLD\n");
			pthread_mutex_unlock(&mutex);//解锁
			sleep(1);
		}
		pthread_exit(NULL);//结束传出参数为空
	}
	
	//创建一个子线程,测试互斥量保证多个线程对共享数据(采用文件秒速符)访问顺序的问题
	int main()
	{
		pthread_t tid;
		pthread_mutex_init(&mutex,NULL);//2.初始化锁,后面要对应销毁,此时mutex=1;
		pthread_create(&tid,NULL,func,NULL);//创建子线程
		for(int i=0;i<5;i++)
		{	
			pthread_mutex_lock(&mutex);//3.加锁
			printf("hello");
			sleep(1);
			printf("world\n");
			pthread_mutex_unlock(&mutex);//4.解锁
			sleep(1);
			
		}
		pthread_cancel(tid);//杀死子线程
		pthread_join(tid,NULL);
		pthread_mutex_destroy(&mutex);//5.释放锁
		pthread_exit(NULL);
	}

运行结果:
在这里插入图片描述
不会出现同时大小写,按顺序访问输出文件描述符.

2.读写锁(只有一把锁)(rwlock)

1>写独占,读共享;写的优先级更高

 #include<stdio.h>
 #include<pthread.h>
 #include<unistd.h>
    /***********************读写锁的控制函数格式:pthread_rwlock_xxx********************************
	*函数1:pthread_mutex_init() 
	*头文件:#include <pthread.h>
	*格式: int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,const pthread_rwlockattr_t *restrict attr);
	*参数:pthread_rwlock_t :结构体,用来定义一个锁(rwlock:取值0(加锁)\1(解锁))e(*restrict作用:限制其他指针对rwlock的地址进行修改,只能本指针完成)
	*参数:const pthread_rwlockattr_t *restrict attr:默认值传入NULL;
	*作用:初始化一个锁(互斥量)
	********************************************************
	*函数2:pthread_rwlock_destroy() 
	*头文件:#include <pthread.h>
	*格式:  int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);//pthread_rwlock_t *rwlock:传入参数,传入锁
	*作用:destroy  a rwlock(读写锁)//与初始化对应
	*返回值:If  successful,  the  pthread_rwlock_destroy()  and pthread_mutex_init() functions shall return  zero;  otherwise,  an  error  number  
	*shall  bereturned to indicate the error.
   	********************************************************
	*函数3-5:pthread_mutex_lock() \pthread_mutex_unlock()\pthread_mutex_trylock()
	*头文件:#include <pthread.h>
	*格式: //加锁是区分了读和写
		int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//作用:对线程进行以读的方式阻塞加锁(如果加锁不成功,就会阻塞在此处),pthread_mutex_t *mutex:传入参数,传入锁名
       		int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);//作用:对线程进以读的方式进行非阻塞加锁
		int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//作用:对线程进行以写的方式阻塞加锁
		int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);//解锁
	*返回值:成功-0;错误-错误号;
	*****************************读写锁的控制函数格式:pthread_rwlock_xxx***************************/
pthread_rwlock_t rwlock;//1.定义读写锁要放在全局变量(子线程能访问)
int test_num;
void * rfunc(void* arg)
	{
		int i=(int)arg;
		usleep(i*100);
		pthread_rwlock_rdlock(&rwlock);//3.加锁,保证在访问共享资源的时候按顺序执行.不会同事进行写操作
		printf("%d th read thread:test_num=%d\n",i+1,test_num);
		pthread_rwlock_unlock(&rwlock);//4.解锁
		pthread_exit(NULL);
	}
void * wfunc(void* arg)
	{
		int i=(int)arg;
		usleep(i*100);
		pthread_rwlock_rdlock(&rwlock);
		test_num=10+i;
		printf("%d th write thread:test_num=%d\n",i+1,test_num);
		pthread_rwlock_unlock(&rwlock);
		pthread_exit(NULL);
	}
	//主线程创建和回收子线,子线成
	int main()
	{
		pthread_t tid[10];
		int i;
		pthread_rwlock_init(&rwlock,NULL);//2.初始化锁,后面要对应销毁;
		//创建线程
		for(i=0;i<10;i++)
		{	
			if(i==3||i==4)
			pthread_create(&tid[i],NULL,wfunc,(void *)i);//创建2个写子线程
			else
			pthread_create(&tid[i],NULL,rfunc,(void *)i);//创建8个读子线程
		}
		//回收线程
		for( i=0;i<10;i++)
		{	
			pthread_join(tid[i],NULL);				
		}
		pthread_rwlock_destroy(&rwlock);//5.释放锁
		pthread_exit(NULL);
	}
	//注意:都没有加入错误检查.

运行结果:
在这里插入图片描述

3.条件变量(cond)

1>条件变量本身不是锁,但它也可以造成程序的阻塞.通常与互斥锁配合使用.与与互斥量比较的优点就是:阻塞时就释放cpu,提高cpu效率
2>口述生产者消费者模型
在这里插入图片描述3>代码实现

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<string.h>
/***********************条件变量的控制函数格式:pthread_cond_xxx********************************
	*函数1:pthread_cond_init() 
	*头文件:#include <pthread.h>
	*格式:int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
	*参数:pthread_cond_t :结构体,用来定义一个条件变量(*restrict作用:限制其他指针对rwlock的地址进行修改,只能本指针完成)
	*参数:const pthread_condattr_t *restrict attr:默认值传入NULL;
	*作用:初始化一个条件变量
	********************************************************
	*函数2:pthread_cond_destroy() 
	*头文件:#include <pthread.h>
	*格式: int pthread_cond_destroy(pthread_cond_t *cond);//pthread_cond_t *cond:传入参数,传入定义的条件变量
	*作用:destroy  a cond//与初始化对应
	*返回值:If successful, the pthread_cond_destroy() and pthread_cond_init() functions shall return zero; otherwise, an error number shall  be  returned to indicate the error.
   	********************************************************
	*函数3:pthread_cond_wait() 
	*头文件:#include <pthread.h>
	*格式: int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
	*参数:pthread_cond_t *restrict cond:定义并初始化好的条件变量
	*参数:pthread_mutex_t *restrict mutex:定义并初始化好的并加锁的互斥量(锁);  
	*作用:1:阻塞等待条件变量cond(参数1)满足;2:释放已经掌握的互斥锁(解锁互斥量)(相当于pthread_mutex_unlock(&mutex));(1-2为原子操作)
	*3:当被唤醒pthread_cond_signal() /pthread_cond_broadcast(),函数会返回时,解除阻塞(这个阻塞是因为pthread_cond_wait()函数造成的)
	*并从新申请获取互斥锁(pthread_mutex_lock(&mutex))
	*返回值:成功-0;错误-错误号;
	********************************************************
	*函数4-5:pthread_cond_signal() /pthread_cond_broadcast()
	*头文件:#include <pthread.h>
	*格式: int pthread_cond_signal(pthread_cond_t *cond);//传入要通知的条件变量(cond)(唤醒至少一个)
			int pthread_cond_broadcast(pthread_cond_t *cond);//(唤醒全部)
	*作用:唤醒pthread_cond_wait()函数
	*返回值:成功-0;错误-错误号;
	********************************************************
	*函数6:pthread_cond_timedwait() 
	*头文件:#include <pthread.h>
	*格式:int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
	*参数:pthread_cond_t *restrict cond :定义并初始化好的条件变量
	*参数:pthread_mutex_t *restrict mutex:定义并初始化好的并加锁的互斥量(锁);
	*参数:const struct timespec *restrict abstime:const struct timespec-结构体,abstime:绝对时间,注意正确使用方法;
	*	 struct timespec {
               time_t tv_sec;       Seconds 
               long   tv_nsec;      Nanoseconds [0 .. 999999999] (纳秒)
           };  
	*作用:到达设定的绝对时间就解除阻塞(pthread_cond_timedwait它的阻塞).即使条件不满足
	*返回值:成功-0;错误-错误号;
	abstime:绝对时间定时法:
	time_t cur=time(NULL);//获取系统当前时间;
	struct timespec t;
	t.tv_sec=cur+1(定时时间)//这里定时的是一秒,然后再把&t传进函数;
	*****************************条件变量的控制函数格式:pthread_cond_xxx**************************/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//使用宏,实现条件变量的定义和初始化(不用在调用pthread_cond_init()函数)
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//定义和初始化互斥锁

//定义一个链表
typedef struct link
{
	int data;
	struct link *next;
}link_t;
struct link *head=NULL;
struct link *temp=NULL;

void *producter(void *arg)
{	
	int num=(int)arg;
	for(int i=1;i<=num;i++)
	{	usleep(500);//保证cpu异主,防止一直生产,产生段错误
		temp=(link_t *)malloc(sizeof( link_t));
		int ret4=pthread_mutex_lock(&mutex);//加锁
		if(ret4!=0)
		printf("pthread_mutex_lock error:%d\n",ret4);
		temp->data=i;
		printf("today %dth data(%d) was producted\n",i,temp->data);
		//头插法
		temp->next=head;
		head=temp;
		int ret5=pthread_mutex_unlock(&mutex);//访问完后,解锁
		if(ret5!=0)
		printf("pthread_mutex_unlock error:%d\n",ret5);
		int ret6=pthread_cond_signal(&cond);//唤醒pthread_cond_wait()
		if(ret6!=0)
		printf("pthread_cond_signal error:%d\n",ret6);
	}
	pthread_exit(NULL);
}

void *consumer(void *arg)
{
	while(1)
	{
		int ret7=pthread_mutex_lock(&mutex);//加锁,一定要在pthread_cond_wait()函数之前
		if(ret7!=0)
		printf("pthread_mutex_lock error:%d\n",ret7);
		while(head==NULL)//不能用if,被唤醒后需要再一次判断是否为空,所以要用while()
		{
			printf("***1\n");
			int ret9=pthread_cond_wait(&cond,&mutex);//如果链表里面为空,则调用pthread_cond_wait()函数,释放本线程已经加锁的互斥锁,并阻塞(让出cpu),等待唤醒(等待生产者生产)
			if(ret9!=0)
			printf("pthread_cond_wait error:%d\n",ret9);
			printf("***2\n");
		}
		temp=head;
		printf("data(%d) was  consumed\n",temp->data);
		head=temp->next;
		int ret8=pthread_mutex_unlock(&mutex);
		if(ret8!=0)
		printf("pthread_mutex_unlock error:%d\n",ret8);
		free(temp);
		temp=NULL;//养成一个好习惯,就是在调用以上两个函数后马上手动赋空,程序对空指针进行多次释放的时候,是不会出错误的。( double free or corruption错误)
	}
}
/********************************************************
*使用条件变量加互斥锁实现生产者和消费者模型
********************************************************/
int main(int argc,char *argv[])
{
	if(argc<2)
	{
		printf("cin number error.");
		exit(1);
	}
	pthread_t pit,cit; //定义两个线程号
	srand((unsigned int)time(NULL));
	//创建两个线程
	int ret0=pthread_create(&pit,NULL,producter,(void *)atoi(argv[1]));
	if(ret0!=0)
	printf("pthread_create error:%d\n",ret0);
	int ret1=pthread_create(&cit,NULL,consumer,NULL);
	if(ret1!=0)
	printf("pthread_create error:%d\n",ret1);
	//回收子线程
	int ret2=pthread_join(pit,NULL);
	if(ret2!=0)
	printf("pthread_join error:%d\n",ret2);
	while(head==NULL)
	{
		printf("***3\n");
		pthread_cancel(cit);//注意:一定要有取消点
		//pthread_cond_signal(&cond);
		printf("***3\n");
		break;
	}
	int ret3=pthread_join(cit,NULL);
	if(ret3!=0)
	printf("pthread_join error:%d\n",ret3);
	//释放条件变量和互斥锁
	pthread_cond_destroy(&cond);
	pthread_mutex_destroy(&mutex);
	pthread_exit(NULL);
}

4.信号量(sem,线程\进程都可以用)

1>前面的三种都是只允许一个线程访问,限制了程序的并发性,而信号量可以允许多个线程对共享数据进行访问,也能保证同步.
2>信号量是进化版的互斥锁,(互斥锁初始化后的mutex等于1,加锁后就–,等于0,解锁后++等于1;信号量初始化时可以指定值(允许多少个线程访问,当为1时,相当于互斥量),sem_wait()函数访问时,信号量大于0,则允许访问,并对信号量–,如果等于0;则阻塞等待sem_post()函数对信号量++,并唤醒sem_wait()函数)
3>条件变量共享数据使用的链表,信号量可以使用队列实现(线性队列\环形队列)
4>信号量实现生产者\消费者模型

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
#include<string.h>
#include <semaphore.h>
/***********************信号量的控制函数格式:sem_xxx********************************
	*函数1:sem_init()  
	*头文件:#include <semaphore.h>
	*格式: int sem_init(sem_t *sem, int pshared, unsigned int value);
	*参数:sem_t *sem:传入参数,sem_t类型,指定信号量
	*参数:int pshared:0-使用于线程中的,!=0-使用与进程;
	*参数:unsigned int value:初始化信号量的值(最大允许访问的线程数)
	*作用:初始化一个信号量
	*注意:Link with -pthread.
	*返回值:sem_init() returns 0 on success; on error, -1 is returned, and errno is set to indicate the error.
	********************************************************
	*函数2:sem_destroy() 
	*头文件:#include <semaphore.h>
	*格式:  int sem_destroy(sem_t *sem);// sem_t *sem:传入参数,传入定义的信号量
	*作用:destroy an unnamed semaphore//与初始化对应
	*返回值: sem_destroy() returns 0 on success; on error, -1 is returned, and errno qis set to indicate the error.
   	********************************************************
	*函数3:sem_wait() \sem_trywait()\sem_timedwait()
	*头文件:#include <semaphore.h>
	*格式:  int sem_wait(sem_t *sem);//如果sem信号量不等于零则访问共享数据,并将sem的值--,如果sem的值已经等于零,则阻塞等待(sem_post()函数将其唤醒).
       		 int sem_trywait(sem_t *sem);  //非阻塞的方式(因此要轮询调用)
      		 int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);//采用绝对时间,到达时间后如果是阻塞等待的,自动放弃阻塞. 
	*作用:加锁,访问共享数据
	*注意:Link with -pthread.
	*返回值:成功-0;错误--1;
	********************************************************
	*函数4:sem_post()
	*头文件:#include <semaphore.h>
	*格式: int sem_post(sem_t *sem);
	*作用:将sem信号量的值+1,如果有线程阻塞在sem_wait()函数,也会将其解除阻塞.
	*返回值:成功-0;错误--1;
	*****************************信号量的控制函数格式:sem_xxx**************************/
#define NUM 5
sem_t blank_num,products_num;//1.定义两个信号量 消费的,生产的
int queue[NUM];  //全局数组实现环形队列
void *product(void * arg)
{	
	int i=0;
	while(1)
	{
		sem_wait(&blank_num);//生产者访问信号量blank_num,并将blank_num--,blank_num=0时,阻塞(最大5个线程).
		queue[i]=rand()%10+1;
		printf("++++++++products %d was producted+++++++++++\n",queue[i]);
		sem_post(&products_num);//唤醒消费者,将信号量products_num++.
		i=i+1%NUM; //i循环变化
		sleep(1);//速度太快会发生段错误
	}
}
void *consume(void * arg)
{
	int i=0;
		while(1)
		{
			sem_wait(&products_num);//消费者访问信号量products_num,并将products_num--,products_num=0时,阻塞(最大5个线程同时访问).
			printf("--------products %d was consumed with cid----------\n",queue[i]);
			queue[i]=0;
			sem_post(&blank_num);//唤醒消费者,将信号量blank_num++.
			i=i+1%NUM; //i循环变化
			sleep(1);//速度太快会发生段错误
		}
}
void *consume1(void * arg)
{
	int i=0;
		while(1)
		{
			sem_wait(&products_num);//消费者访问信号量products_num,并将products_num--,products_num=0时,阻塞(最大5个线程同时访问).
			printf("---------products %d was consumed with cid1----------\n",queue[i]);
			queue[i]=0;
			sem_post(&blank_num);//唤醒消费者,将信号量blank_num++.
			i=i+1%NUM; //i循环变化
			sleep(1);//速度太快会发生段错误
		}
}
/********************************************************
*使用信号量实现生产者和消费者模型
********************************************************/
int main(int argc,char *argv[])
{
	pthread_t pid,cid,cid1;
	if(argc<2)
	{
		printf("cin number error.\n");
		exit(1);
	}
	srand((unsigned int)time(NULL));
	//2.信号量变量初始化
	sem_init(&blank_num,0,NUM);//刚开始,空格子信号量为5,最大允许5个生产者访问;
	sem_init(&products_num,0,0);//刚开始,产品数量为0;不允许消费者访问.
	//创建生产和消费线程
	pthread_create(&pid,NULL,product,NULL);
	pthread_create(&cid,NULL,consume,NULL);
	pthread_create(&cid1,NULL,consume1,NULL);
	//线程回收
	pthread_join(pid,NULL);
	pthread_join(cid,NULL);
	pthread_join(cid1,NULL);
	//3释放信号量
	sem_destroy(&pid);
	sem_destroy(&cid);
	pthread_exit(NULL);
}
//注意返回值检查;

运行结果:
在这里插入图片描述

进程同步

1.信号量(sem,线程\进程都可以用)这里就不累赘

2.互斥量(锁)(mutex)

1>与线程中的互斥锁唯一的差别就是在调pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);第二个参数不能传NULL;而要修改为进程锁,步骤如下:
在这里插入图片描述
说明:先定义pthread_mutexattr_t 结构体变量(pthread_mutexattr_t是一个结构体),然后调用三个函数.

3.文件锁

1>只能用在进程中,以为线程的fd(文件描述符共享),调用fcntl()函数没有用.线程里有读写锁可以使用.
2>读时共享,写时独占
3>代码实现

#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdlib.h>
#include <sys/wait.h>
	/*******************************************************
	*函数:fcntl() //借助该函数实现,操作文件的进程没有获得锁时,可以打开文件,但是没有read\write的权限
	*头文件:#include<unistd.h>\#include<fcntl.h>
	*格式:  int fcntl(int fd, int cmd, ... /* arg */ //);//变参函数,后面的参数有cmd决定.
	/*参数1:文件描述符;参数2:三个取值:F_SETLK-设置文件锁(不会阻塞 trylock), F_SETLKW-设置文件锁(会阻塞,W-lock), 
	*F_GETLK-获取文件锁;(三个取值都是struct flock*类型的)参数3:struct flock:
	struct flock {
			   ...
			   short l_type;    // Type of lock: F_RDLCK,F_WRLCK, F_UNLCK (以读的方式加锁,写的方式加锁,解锁)原则:写时独享,读时共享
			   short l_whence;  // How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END (文件加锁的开始位置)
			   off_t l_start;   // Starting offset for lock (相对于文件加锁开始位置偏移量)
			   off_t l_len;     // Number of bytes to lock (文件加锁的长度)
			   pid_t l_pid;     // PID of process blocking our lock(set by F_GETLK and F_OFD_GETLK),获取进程的pid,F_SETLK和F_SETLKW时不能用.
			   ...
		   };
	参数2有三个取值,且都是struct flock*类型,所以参数3传入一个struct flock结构体,来设置对应的属性.
	*作用:获取\设置文件访问控制属性.
	*返回值:成功-0,失败--1;
	********************************************************/
void myperror(char *str[])
{
	perror(str);
	exit(1);
}
//使用文件锁,一个进程读,一个进程写的属性加锁测试
int main(int argc,char *argv[])
{
	if(argc<2)
	{
		printf("cin param error");
		exit(1);
	}
	pid_t pid;
	
	 pid=fork();
	if(pid==-1)
	{
		myperror("fork error");
	}
	//子进程以读的方式加锁
	if(pid==0) 
	{	
		//打开文件
		int fd=open(argv[1],O_RDWR);
		if(fd==-1)
		{
			myperror("open error");
		}
		//1.定义结构体
		struct flock  file_lock;  //不能定义为指针
		//2.设置加锁属性
		file_lock.l_type=F_RDLCK;			//读的方式加锁
		file_lock.l_whence=SEEK_SET;
		file_lock.l_start=0;
		file_lock.l_len=0;					//等于0,对全部文件加锁.
		//3.加锁
		sleep(1);//保证父进程先加锁,验证写时独享,读时共享
		fcntl(fd,F_SETLKW,&file_lock); //加锁,解锁都调用该函数.(F_SETLKW:加锁不成功会阻塞)
		printf("child process lock file %s successed.\n",argv[1]);
		sleep(5);
		printf("sleep 5s successed\n");
		//4.设置属性
		file_lock.l_type=F_UNLCK;
		//5.解锁
		fcntl(fd,F_SETLKW,&file_lock); //加锁,解锁都调用该函数.(第二个参数不变F_SETLKW)
		printf("child process unlock file %s successed.\n",argv[1]);
		close(fd);
	}
	//父进程以写的方式加锁
	if(pid>0) 
	{	
		//打开文件
		int fd1=open(argv[1],O_RDWR);
		if(fd1==-1)
		{
			myperror("open error");
		}
		//1.定义结构体
		struct flock  file_lock1;
		//2.设置加锁属性
		file_lock1.l_type=F_WRLCK;			//写的方式加锁
		file_lock1.l_whence=SEEK_SET;
		file_lock1.l_start=0;
		file_lock1.l_len=0;					//等于0,对全部文件加锁.
		//3.加锁
		int ret1=fcntl(fd1,F_SETLKW,&file_lock1);//加锁,解锁都调用该函数.(F_SETLKW:加锁不成功会阻塞)
		if(ret1==-1)//此处报错 11-27
		{
			myperror("fcntl1 error");
		}
		printf("parent process lock file %s successed.\n",argv[1]);
		sleep(5);
		printf("sleep 5s successed\n");
		//4.设置属性
		file_lock1.l_type=F_UNLCK;
		//5.解锁
		fcntl(fd1,F_SETLKW,&file_lock1);//加锁,解锁都调用该函数.(第二个参数不变F_SETLKW)
		printf("parent process unlock file %s successed.\n",argv[1]);
		close(fd1);
		wait(NULL);			//回收子进程
	}
	return 0;
}

运行结果:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值