Linux——线程同步和线程安全

Linux——线程同步和线程安全


1线程同步

同步:多进程或者多线程访问临界资源时,必须进行同步控制。多进程或者多线程的

执行并不完全是绝对的并行运行,有可能主线程需要等待函数线程的某些条件的发生。


多线程之间有几个特殊的临界资源:

全局数据、堆区数据、文件描述符多线程之间共用。


线程间同步控制方式:

1.1信号量#include<semaphore.h>

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

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

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

value:信号量的初始值

返回值:0成功-1失败

P操作intsem_wait(sem_t *sem); //阻塞运行

V操作intsem_post(sem_t *sem);

删除:int sem_destroy(sem_t *sem);

练习:

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

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

char buff[128] = {0};
sem_t sem;

void *pthread_fun(void *arg)
{
	sem_wait(&sem);
	while(1)
	{
		sem_wait(&sem);
		if(strncmp(buff,"end",3) == 0)
		{
			break;
		}
		printf("buff length: %d\n",strlen(buff) - 1);
	}
}


void main()
{
	pthread_t id;
	sem_init(&sem,0,0);
	int res = pthread_create(&id, NULL, pthread_fun, NULL);
	assert(res == 0);

	while(1)
	{
		printf("[please input] ");
		fflush(stdout);
		fgets(buff,128,stdin);
		sem_post(&sem);
		if(strncmp(buff,"end",3) == 0)
		{
			break;
		}

	}
	pthread_join(id,NULL);
}

运行结果:





1.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_unlock(pthread_mutex_t *mutex);

释放:

int pthread_mutex_destroy(pthread_mutex_t *mutex);

1.3条件变量

2线程安全--->可重入函数

有些库函数会使用线程间共享的数据,如果没有同步控制,线程操作就是不安全的,

所以,我们使用这样一些函数时,就必须使用其安全的版本---可重入函数

 

 

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

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

会启用。

子进程会继承其父进程的锁以及锁的状态,但是父子进程用的不是同一把锁,父进

程解锁并不会影响到子进程的锁,所以子进程有可能死锁!!!

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

指定在fork调用之后,创建子进程之前,调用prepare函数,获取所有的锁,

然后创建子进程,子进程创建以后,父进程环境中调用parent解所有的锁,子进

程环境中调用child解所有的锁,然后fork函数再返回。这样保证了fork之后,子进程

拿到的锁都是解锁状态,避免死锁。

扩展:

同一个线程中,对于用一把锁,加锁和解锁之间需要一定时间。信号量需不需要?

读写锁自旋锁......的作用以及用法

未完。。。



版权声明:本文为zm_2209068178原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。