同进程内的所有线程共同使用进程的内存空间,并且线程可以在直接应用层完成,因此线程和线程之间的通信使用“全局变量”即可完成通信。但是由于 Linux 系统没有数据保护方式,所在在线程通信的时候需要进行数据的“同步保护”。
在同进程中的多个线程都要操作的数据进行保护时,只允许一个线程操作要保护的内容。Linux 系统使用“信号量”、“互斥锁”以及“条件变量”来实现数据同步保护。实现数据保护的流程为:
①创建一种使用的保护机制(信号量、互斥锁或条件变量)。
②在操作保护内容之前,加保护(一旦本线程加保护成功,其他线程在操作就会阻塞)。
③在操作保护内容后,解保护(其他线程自动取消阻塞)。
④删除保护机制。
注:线程间的数据保护机制是一种人为的约束,一定要所有线程都要遵循这个操作才会有意义,同时“加保护”、“解保护”操作在一个线程中一定要成对出现。
头文件
#include
函数原型:int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
参数介绍:
mutex:互斥锁编号。
attr:互斥锁的属性。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
pthread_mutex_t mutexid;
pthread_mutex_init(&mutexid,NULL);
头文件
#include
函数原型:int pthread_mutex_lock(pthread_mutex_t *mutex);
参数介绍:
mutex:互斥锁编号。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
pthread_mutex_lock(&mutexid);
头文件
#include
函数原型:int pthread_mutex_unlock(pthread_mutex_t *mutex);
参数介绍:
mutex:互斥锁编号。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
返回值:
pthread_mutex_unlock(&mutexid);
头文件
#include
函数原型:int pthread_mutex_destroy(pthread_mutex_t *mutex)
参数介绍:
mutex:互斥锁编号。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
返回值:
pthread_mutex_destroy(&mutexid);
头文件
#include
函数原型:int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
参数介绍:
cond:条件变量编号。
mutex:条件变量的属性。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
pthread_cond_t condid;
pthread_cond_init(&condid,NULL);
头文件
#include
函数原型:int pthread_cond_signal(pthread_cond_t *cond);
参数介绍:
cond:条件变量编号。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
pthread_cond_signal(&condid);
头文件
#include
函数原型:int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
参数介绍:
cond:条件变量编号。
mutex:条件变量的属性。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
pthread_cond_wait(&condid,&mutexid);
头文件
#include
函数原型:int pthread_cond_destroy(pthread_cond_t *cond);
参数介绍:
cond:条件变量编号。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
pthread_cond_destroy(&condid);
头文件
#include
函数原型:==int sem_init(sem_t *sem, int pshared, unsigned int value); ==
参数介绍:
sem:信号量编号。
pshared:信号量在作用范围(0:本进程中多个线程共享可用;非 0:在当前登录用户的多个进程之间共享)。
value:信号量的信号值。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
sem_t semid;
sem_init(&semid,0, 1);
头文件
#include
函数原型:int sem_wait(sem_t * sem);
参数介绍:
sem:信号量编号。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
sem_wait(&semid);
头文件
#include
函数原型:int sem_post(sem_t * sem);
参数介绍:
sem:信号量编号。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
sem_post(&semid);
头文件
#include
函数原型:int sem_destroy(sem_t * sem);
参数介绍:
sem:信号量编号。
返回值:成功返回 0,失败返回-1,并且设置 errno 变量来指示错误的发生。
sem_destroy(&semid);
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
char path[10];
//信号服务函数
void * son_fun(void * arg)
{
int fd2 = open(path,O_RDWR); //打开读管道
while(1)
{
char rb[512] = {0};
read(fd2,rb,sizeof(rb));
printf("%s说:%s\n",(char *)arg,rb);
}
close(fd2); //关闭读管道
}
//关于argv:
// 1 是读通道 2 是写通道 3 是自己的信号 4 是发的信号
int main(int argc,char *argv[])
{
//init
pthread_t id;
strcpy(path,argv[2]);
//创建管道
int val1 = mkfifo(argv[1],0666);
int val2 = mkfifo(argv[2],0666);
//打开管道
int fd1 = open(argv[1],O_RDWR); //写管道
//创建子线程
pthread_create(&id,NULL,son_fun,"he say");//创建子线程
//等待写入
while(1)
{
char wb[512] = {0};
gets(wb);
write(fd1,wb,strlen(wb));
}
close(fd1);
pthread_join(id,NULL);
return 0;
}