Linux--线程下

信号量 – 线程级

信号量类似于一个特殊的计数器,当信号量值大于零,表示可以访问的临界资源的个数,等于零,对信号量执行P操作会阻塞
对信号量的P,V操作不一定非得在同一线程中
信号量方法:
#include <semaphore.h>
信号量类型:sem_t 全局定义一个sem_t类型的信号量
初始化:int sem_init(sem_t *sem, int shared, int init_val);
shared:设置信号量是否在进程间共享,Linux不支持,一般给零
init_val:信号量的初始值
P操作:int sem_wait(sem_t *sem);
V操作:int sem_post(sem_t *sem);
销毁:int sem_destroy(sem_t *sem);

示例:主线程 函数线程
主线程获取用户输入,函数线程将用户输入的数据存储到a.txt中。
1.主线程获取的用户数据如何传递给函数线程:全局 堆区 栈区(空间指针需要传入才可共享)
2.函数线程只能在主线程获取到数据(直接存储在共享空间中),才能执行write操作
3.主线程只能在函数线程将数据写入文件后才能获取下一次数据

代码实现:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <fcntl.h>
#include <signal.h>

#include <semaphore.h>
#include <pthread.h>
#define BUFFSIZE 128
sem_t sem1,sem2;
void *fun(void *arg)
{

	char *buff = (char *)arg;
	int fw = open("a.txt",O_WRONLY | O_CREAT | O_TRUNC,0664);
	assert(fw != -1);
	while(1)
	{
		sem_wait(&sem1);

		if(strncmp(buff,"end",3) == 0)
			break;

		write(fw,buff,strlen(buff));
		memset(buff,0,BUFFSIZE);
		sem_post(&sem2);
	}
}
int main()
{

	sem_init(&sem1,0,0);
	sem_init(&sem2,0,2);

	char buff[BUFFSIZE] = {0};
	pthread_t id;
	int res = pthread_create(&id,NULL,fun,(void *)buff);
	assert(res == 0);

	while(1)
	{
		sem_wait(&sem2);
		printf("please input: ");
		fgets(buff,BUFFSIZE,stdin);

		sem_post(&sem1);
		if(strncmp(buff,"end",3) == 0)
			break;
	}
	pthread_join(id,NULL);
	sem_destroy(&sem1);
	sem_destroy(&sem2);
	exit(0);
}

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

条件变量

为多个线程提供一个汇合的场所
在这里插入图片描述
wait再加锁状态下,将线程添加到条件变量对应的等待队列中,然后执行解锁操作 – 》将线程添加到队列与唤醒是互斥的
(用互斥锁保护,假如同时有两个线程,一个进行添加,一个进行唤醒,如果没有互斥锁保护,就不知道到底是添加还是唤醒,加上互斥锁,就是在添加的时候不能唤醒,唤醒的时候不能添加,更安全)

读写锁

在这里插入图片描述
读写锁有三种状态:读模式下加锁,写模式下加锁,不加锁,一次只能有一个线程占有写模式读写锁,但是多个线程可以同时占有读模式读写锁
如果当前是读加锁,另外一个线程试图写加锁请求,那么之后的读加锁都会阻塞,这样可以避免读模式长期被占用,写加锁请求却不能得到满足


线程安全

线程是并发运行的,而且线程之间共享进程的地址空间,所以在执行时,可能会修改共享数据,修改的时机也无法确定,所以最后的结果有不确定性
1.使用线程同步
2.不使用共享数据 – 》共享数据转化为非共享数据

不能保证线程安全的库函数:
在这里插入图片描述
(方法种使用了全局或者数据可以共享的变量,所以不安全)

1.多线程种某个线程调用fork(),子进程会有和父进程相同数量的进程嘛?
多线程种一个线程调用fork创建子进程,子进程种只有fork这个线程会被启动运行,其他线程不会运行。


2.父进程被加锁的互斥锁fork后在子进程中是否已经加锁
多线程种调用fork创建子进程,子进程会继承父进程的锁的状态,父进程中所有的对锁的的操作都不能影响子进程的锁的状态。就会出现死锁,所以在多线程中执行fork之前,需要调用pthread_atfork方法,保证继承的锁绝对是解锁状态

pthread_atfork是一个注册方法,注册了三个函数,这三个函数在不同时间执行
在这里插入图片描述
atfork注册的三个方法,以及其调用时机,都是为了保证在fork执行过程中,所有的锁都是枷锁状态,没有其他线程会加锁成功。fork完成之后,分别在父进程空间和子进程空间解锁,fork之后,父进程的使用的锁都是解锁状态的

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值