Linux同步相关

线程同步

指一个线程发出某一功能调用时,在没有得到结果之前,该调用不返回。同时线程为保证数据一致性,不能调用该功能。
协同步调,对公共区域数据按序访问。防止数据混乱,产生与时间有关的错误。

互斥量(互斥锁)

在这里插入图片描述

pthread_mutex_t lock;//创建锁
pthread_mutex_init;//初始化
pthread_mutex_lock;//加锁
访问共享数据(stdout)
pthread_mutex_unlock;//解锁
pyhread_mutex_destory;//销毁锁

restrict 关键字:
  用来限定指针变量。被该关键字限定的指针变量所指向的内存操作,必须由本指针操作。

在这里插入图片描述
注意事项:
尽量保证锁的粒度越小越好。(访问数据共享数据前,立即加锁。访问结束立即解锁。)
互斥锁,本质是结构体,可以看成初值为1.(pthread_mutex_init()函数调用成功)。
加锁 --操作
解锁 ++ 操作
try锁:尝试加锁,成功–。失败,返回,同时设置错误号为EBUSY。
死锁
使用所不恰当导致的现象。
1.对一个锁反复lock。
2.两个线程各自持有一把锁,去申请不属于自己的那把锁。
在这里插入图片描述

进程间mutex

在这里插入图片描述

读写锁

锁只有一把。以读方式给数据加锁–读锁。写方式–写锁。
读共享,写独占。
写锁优先级高。
在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

int counter;
pthread_rwlock_t rwlock;//创建一把全局锁

void *tf_read(void *arg)
{
	int i = (int)arg;
	while(1){
		pthread_rwlock_rdlock(&rwlock);//读锁
		printf("-----------read %d:%lu:%d\n",i,pthread_self(),counter);
		pthread_rwlock_unlock(&rwlock);//解锁
		usleep(2000);
	}
	return NULL;
}

void *tf_write(void *arg)
{
	int t;
	int i = (int)arg;
	while(1){
		pthread_rwlock_wrlock(&rwlock);
		t = counter;
		usleep(1000);
		printf("============write%d:%lu:counter = %d ++counter = %d\n",i,pthread_self(),t,++counter);
		pthread_rwlock_unlock(&rwlock);
		usleep(10000);
	}
	return NULL;
}

int main()
{
	int i;
	pthread_t tid[8];

	pthread_rwlock_init(&rwlock,NULL);//初始化锁

	for(i = 0; i < 3; i++)
		pthread_create(&tid[i],NULL,tf_write,(void *)i);

	for(i = 0; i < 5; i++)
		pthread_create(&tid[i+3],NULL,tf_read,(void *)i);

	for(i = 0; i < 8; i++)
		pthread_join(tid[i],NULL);//回收线程

	pthread_rwlock_destroy(&rwlock);//销毁锁

	return 0;
}

条件变量

本身不是锁!通常结合互斥锁使用。
在这里插入图片描述
pthread_cond_t cond;
初始化条件变量:
1.pthread_cond_init(&cond,NULL);动态初始化
2.pthread_cond_t cond = PTHREAD_COND_INITIALIZER;静态初始化
互斥锁也可以这样初始化

在这里插入图片描述
在这里插入图片描述

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

struct msg{
	int num;
	struct msg *next;
};

struct msg *head;

void *fn_p(void *arg)
{
	while(1){
		struct msg *mp = malloc(sizeof(struct msg));
		mp->num =rand()%1000 + 1;
		printf("produce %d\n",mp->num);
		pthread_mutex_lock(&mutex);
		mp->next = head;
		head = mp;
		pthread_mutex_unlock(&mutex);
		pthread_cond_signal(&cond);
		sleep(rand()%3);
	}
	return NULL;
}

void *fn_c(void *arg)
{
	while(1){
		struct msg *mp;
		pthread_mutex_lock(&mutex);//加锁
		while(head == NULL){//这里while是为了多个消费者的时候判断
			pthread_cond_wait(&cond,&mutex);
		}
		mp = head;
		head = mp->next;
		pthread_mutex_unlock(&mutex);
		printf("consume %d",mp->num);
		free(mp);
		sleep(rand()%3);
	}
	return NULL; 
}

int main()
{
	pthread_t pid,cid;

	srand(time(NULL));

	pthread_create(&pid,NULL,fn_p,NULL);//生产者线程
	pthread_create(&cid,NULL,fn_c,NULL);//消费者线程,尽量检查返回值

	pthread_join(pid,NULL);
	pthread_join(cid,NULL);

	return 0;
}

pthread_cond_signal:唤醒阻塞在条件变量上的(至少)一个线程。(可以唤醒多个)
pthread_cond_broadcast:唤醒阻塞在条件变量上的所有线程

信号量

应用于线程,进程。
相当于初始化值为n的互斥量。
在这里插入图片描述
在这里插入图片描述

sem_t sem;
int sem_init(sem_t *sem, int pshared, unsigned int value);
参数:
	sem 信号量
	pshard 0:用于线程间同步
		   1:用于进程间同步
	value:N值。(指定同时访问的进程数)
sem_wait(&sem);加锁
sem_post(&sem);解锁

在这里插入图片描述

文件锁

进程锁,不能在线程使用,因为线程文件描述符共享
在这里插入图片描述
第二个函数即关闭锁,又开锁,修改属性达到目的。在这里插入图片描述

struct flock lock;
lock.l_type = F_RDLOCK;
fcntl(fd,F_SETLKW,&lock);//加锁
lock.l_type = F_UNLOCK;
fcntl(fd,F_SETLKW,&lock);//解锁

在这里插入图片描述
哲学家就餐问题,记得回来写

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值