linux线程通信
2015-09-20 00:41
459 查看
线程
进程是系统分配资源的基本单位
线程是系统调度的基本单位,共享进程的全部资源
一个进程可以有一个或者多个线程,线程一定对应一个进程
线程的属性之一:detach mode 默认是非分离状态,也就是需要主线程去回收资源的,用的是join。
就绪---> 运行态 ---> 阻塞 ---> 就绪
创建 : 进程fork线程:pthread_create
回收资源: waitpthread_join
结束 exit、_exitpthread_exit / pthread_cancel
注册退出处理:
atexit pthread_cleanup_push & pthread_cleanup_pop
获得ID getpidpthread_self
fork得到子进程ID pthread_create也可以得到子线程ID
pthread_equal(pthread_t , pthread_t );
在线程中return (void *)0; 返回到调用线程
exit (0); 直接退出了进程
都能令线程正常终止
pthread_cancel(tid)只是调用者的愿望,tid对应的线程是否退出则需要看线程是否处于运行态
处于运行态的线程是不去响应这个cancel的
针对非分离线程才有效,如果是线程已经分离,直接返回出错信息
pthread_equal(pthread_t , pthread_t );
pthread_t tid = pthread_self();
pthread_exit();
分离线程怎么创建
1: 从线程的属性上去设置分离或者非分离(默认)
属性:
pthread_attr_t attr
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid , 属性,线程函数入口,线程函数参数)
2: 从线程函数中,必须放在第一句 pthread_detach()
3: 一定要保证在线程调用 pthread_join(tid,NULL)之前,
就已经调用过pthread_detach(tid)或者是子线程中的pthread_detach(pthread_self())),这样才能生效
主线程不想或者不能阻塞在对该子线程的回收上时候, 希望子线程能够独立行事
pthread_cleanup_push & pthread_cleanup_pop
成对出现, 不能被分开,
两个都是宏定义 , 暗含了{ 和}
如果代码在push和POP之间退出(不包含return)了, 那就会调用push中注册的函数
调用函数的顺序和压栈、出栈顺序一致
pthread_cleanup_push {
{
}
pthread_cleanup_pop }
pthread_cleanup_pop(val) : val= 0:执行到pop语句的时候,不会调用push中注册的退出处理函数
= 1:执行到pop语句的时候,会调用push中注册的退出处理函数
线程间通信:
同步互斥机制:
信号量 sem ----------------- 同步机制 POSIX
互斥锁 mutex
条件变量 pthread_cond 广播条件 等待条件成立
读写锁 rwlock
spin
信号量
sem_init
sem_wait -- P 申请资源 sem_trywait sem_timedwait
sem_post -- v 释放资源
互斥锁
pthread_mutex_init
pthread_mutex_lock / pthread_mutex_trylock
pthread_mutex_unlock
pthread_mutex_destroy
条件变量 (类似于信号)
pthread_cond_init
pthread_cond_wait()
偷解锁,在解锁状态下等待,得到条件变量后再次上锁
pthread_cond_timedwait()
pthread_cond_signal()发送一次给等待该条件变量的一个进程
pthread_cond_broadcast() 发送给所有等待该条件变量的进程
pthread_cond_destroy()
注意:
临界资源(上锁和解锁之间的代码)应该尽可能简短,最好不要有延时之类的操作
一定在线程退出的时候,注意是否需要有释放锁的动作,
特别是在代码中途出现异常而退出的时候
--------------------------------------
信号量:sem
基本操作: init sem_init (sem_t * , 0 , 1)
pshared == 1 表示在进程间使用该信号量,需要用到共享内存中的地址
P 操作 sem_wait() 申请资源,申请到资源就信号量-1; 如果信号量为0,则会阻塞到信号量非零才返回;
sem_trywait 申请资源,申请到资源就信号量-1;如果信号量为0直接返回
sem_timedwait 申请资源,申请到资源就信号量-1;如果信号量为0就等一段时间,还等不到就直接返回
V 操作 sem_post() 释放资源,信号量+1,而且唤醒睡眠中的等待该资源的线程或者进程
互斥锁:mutex
pthread_mutex_init(pthread_mutex_t * , NULL)
restrict 表示只能通过该指针来修改该指针指向的内容
pthread_mutex_lock (pthread_mutex_t *)上锁 堵塞等待可上锁
pthread_mutex_trylock 如果已经上锁就直接返回。和锁的属性有关系, PTHREAD_MUTEX_RECURSIVE是会增加锁的个数
pthread_mutex_unlock (pthread_mutex_t *)解锁
pthread_mutex_destroy (pthread_mutex_t *) 锁就变成不可用
实例:
实现Jack线程和Rose线程,并发送到消息队列,要求双方可以一直通信,直到互说88 结束线程
使用互斥锁通信
进程是系统分配资源的基本单位
线程是系统调度的基本单位,共享进程的全部资源
一个进程可以有一个或者多个线程,线程一定对应一个进程
线程的属性之一:detach mode 默认是非分离状态,也就是需要主线程去回收资源的,用的是join。
就绪---> 运行态 ---> 阻塞 ---> 就绪
创建 : 进程fork线程:pthread_create
回收资源: waitpthread_join
结束 exit、_exitpthread_exit / pthread_cancel
注册退出处理:
atexit pthread_cleanup_push & pthread_cleanup_pop
获得ID getpidpthread_self
fork得到子进程ID pthread_create也可以得到子线程ID
pthread_equal(pthread_t , pthread_t );
在线程中return (void *)0; 返回到调用线程
exit (0); 直接退出了进程
都能令线程正常终止
pthread_cancel(tid)只是调用者的愿望,tid对应的线程是否退出则需要看线程是否处于运行态
处于运行态的线程是不去响应这个cancel的
针对非分离线程才有效,如果是线程已经分离,直接返回出错信息
pthread_equal(pthread_t , pthread_t );
pthread_t tid = pthread_self();
pthread_exit();
分离线程怎么创建
1: 从线程的属性上去设置分离或者非分离(默认)
属性:
pthread_attr_t attr
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid , 属性,线程函数入口,线程函数参数)
2: 从线程函数中,必须放在第一句 pthread_detach()
3: 一定要保证在线程调用 pthread_join(tid,NULL)之前,
就已经调用过pthread_detach(tid)或者是子线程中的pthread_detach(pthread_self())),这样才能生效
主线程不想或者不能阻塞在对该子线程的回收上时候, 希望子线程能够独立行事
pthread_cleanup_push & pthread_cleanup_pop
成对出现, 不能被分开,
两个都是宏定义 , 暗含了{ 和}
如果代码在push和POP之间退出(不包含return)了, 那就会调用push中注册的函数
调用函数的顺序和压栈、出栈顺序一致
pthread_cleanup_push {
{
}
pthread_cleanup_pop }
pthread_cleanup_pop(val) : val= 0:执行到pop语句的时候,不会调用push中注册的退出处理函数
= 1:执行到pop语句的时候,会调用push中注册的退出处理函数
线程间通信:
同步互斥机制:
信号量 sem ----------------- 同步机制 POSIX
互斥锁 mutex
条件变量 pthread_cond 广播条件 等待条件成立
读写锁 rwlock
spin
信号量
sem_init
sem_wait -- P 申请资源 sem_trywait sem_timedwait
sem_post -- v 释放资源
互斥锁
pthread_mutex_init
pthread_mutex_lock / pthread_mutex_trylock
pthread_mutex_unlock
pthread_mutex_destroy
条件变量 (类似于信号)
pthread_cond_init
pthread_cond_wait()
偷解锁,在解锁状态下等待,得到条件变量后再次上锁
pthread_cond_timedwait()
pthread_cond_signal()发送一次给等待该条件变量的一个进程
pthread_cond_broadcast() 发送给所有等待该条件变量的进程
pthread_cond_destroy()
注意:
临界资源(上锁和解锁之间的代码)应该尽可能简短,最好不要有延时之类的操作
一定在线程退出的时候,注意是否需要有释放锁的动作,
特别是在代码中途出现异常而退出的时候
--------------------------------------
信号量:sem
基本操作: init sem_init (sem_t * , 0 , 1)
pshared == 1 表示在进程间使用该信号量,需要用到共享内存中的地址
P 操作 sem_wait() 申请资源,申请到资源就信号量-1; 如果信号量为0,则会阻塞到信号量非零才返回;
sem_trywait 申请资源,申请到资源就信号量-1;如果信号量为0直接返回
sem_timedwait 申请资源,申请到资源就信号量-1;如果信号量为0就等一段时间,还等不到就直接返回
V 操作 sem_post() 释放资源,信号量+1,而且唤醒睡眠中的等待该资源的线程或者进程
互斥锁:mutex
pthread_mutex_init(pthread_mutex_t * , NULL)
restrict 表示只能通过该指针来修改该指针指向的内容
pthread_mutex_lock (pthread_mutex_t *)上锁 堵塞等待可上锁
pthread_mutex_trylock 如果已经上锁就直接返回。和锁的属性有关系, PTHREAD_MUTEX_RECURSIVE是会增加锁的个数
pthread_mutex_unlock (pthread_mutex_t *)解锁
pthread_mutex_destroy (pthread_mutex_t *) 锁就变成不可用
实例:
实现Jack线程和Rose线程,并发送到消息队列,要求双方可以一直通信,直到互说88 结束线程
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <sys/msg.h> struct msg_st { long int msg_type;// !!!!!!必须 long msg_type_using; // 1:n 因为第一个参数msg_type是不能从data中获得的,所以多设置一个 char buf[20]; }; int msgid = -1; void *myThread1(void) { struct msg_st data; long int msgtype = 1; // 0; // 2; //注意1 0 while(1) { memset(data.buf,0,sizeof(data.buf)); if(msgrcv(msgid, (void*)&data, (sizeof(struct msg_st) - sizeof(long int)), msgtype, 0) == -1) { fprintf(stderr, "msgrcv failed with errno: %d\n", errno); exit(EXIT_FAILURE); } printf("myThread1 receive %s \n", data.buf); //结束 if(strncmp(data.buf,"88",strlen("88"))==0) { printf("88\n"); break; } data.msg_type = 2; //printf ("send to %ld : sum = %d \n", data.msg_type,data.sum); printf ("myThread1 send to a string:"); fgets(data.buf,sizeof(data.buf),stdin); if(msgsnd(msgid, (void*)&data, (sizeof(struct msg_st) - sizeof(long int)), 0) == -1) { fprintf(stderr, "msgsnd failed\n"); exit(EXIT_FAILURE); } } pthread_exit(NULL); } void *myThread2(void) { int msgtype; struct msg_st data; while(1) { printf ("myThread2 send to a string:"); fgets(data.buf,sizeof(data.buf),stdin); data.msg_type = 1; if(msgsnd(msgid, (void*)&data, (sizeof(struct msg_st) - sizeof(long int)), 0) == -1) { fprintf(stderr, "msgsnd failed\n"); exit(EXIT_FAILURE); } memset(data.buf,0,sizeof(data.buf)); msgtype = 2; if(msgrcv(msgid, (void*)&data, (sizeof(struct msg_st) - sizeof(long int)), msgtype, 0) == -1) { fprintf(stderr, "msgrcv failed with errno: %d\n", errno); exit(EXIT_FAILURE); } printf("myThread2 receive %s \n", data.buf); if(strncmp(data.buf,"88",strlen("88")) ==0 ) { printf("88\n"); break; } //data.msg_type = data.msg_type_using +1; } pthread_exit(NULL); } int main() { int i=0, ret=0; pthread_t tid1,tid2; //建立消息队列 msgid = msgget((key_t)1234, 0666 | IPC_CREAT); if(msgid == -1) { fprintf(stderr, "msgget failed with error: %d\n", errno); exit(EXIT_FAILURE); } printf("msgid = %d",msgid); printf("main creat thread1\n"); ret = pthread_create(&tid1, NULL, (void*)myThread1, NULL); if (ret) { perror("Create pthread1 error:\n"); return 1; } printf("main creat thread2\n"); ret = pthread_create(&tid2, NULL,(void*) myThread2, NULL); if (ret) { perror("Create pthread2 error:"); return 1; } pthread_join(tid1,NULL); pthread_join(tid2,NULL); while(1) { sleep(1); } return 0; }
使用互斥锁通信
#include <stdio.h> #include <pthread.h> #include "stdlib.h" #include "unistd.h" pthread_mutex_t mutex; pthread_cond_t cond; void hander(void *arg) { printf("exit in hander \n"); free(arg); (void)pthread_mutex_unlock(&mutex); } void *thread1(void *arg) { pthread_cleanup_push(hander, &mutex); while(1) { printf("thread1 is running\n"); pthread_mutex_lock(&mutex); // 上锁1 printf("thread1 waiting ... \n"); pthread_cond_wait(&cond,&mutex); // 偷解锁,在解锁状态下等待,得到条件变量后再次上锁 printf("thread1 applied the condition\n"); pthread_mutex_unlock(&mutex);// 必须匹配LOCK // sleep(4); } pthread_cleanup_pop(0); } void *thread2(void *arg) { while(1) { printf("thread2 is running\n"); pthread_mutex_lock(&mutex);// 上锁2 printf("thread2 waiting ... \n"); pthread_cond_wait(&cond,&mutex);// 偷解锁,在解锁状态下等待,得到条件变量后再次上锁 printf("thread2 applied the condition\n"); pthread_mutex_unlock(&mutex); // sleep(1); } } int main() { pthread_t thid1,thid2; printf("condition variable study!\n"); pthread_mutex_init(&mutex,NULL);//互斥锁 pthread_cond_init(&cond,NULL); // 条件变量 pthread_create(&thid1,NULL,thread1,NULL); pthread_create(&thid2,NULL,thread2,NULL); sleep(1); do { printf("signal cond \n"); pthread_cond_broadcast(&cond); //pthread_cond_signal(&cond); sleep(2); }while(1); sleep(20); pthread_exit(0); return 0; }
相关文章推荐
- Zookeeper linux下使用
- linux-软件包管理
- centos5.x安装Mysql笔记
- Configuring VM Acceleration on Linux
- CentOS下安装JDK1.7
- 在Linux下安装RabbitMQ
- linux创建线程
- 构建centos 5.2系统源码树
- Centos7下安装Chrome浏览器
- linux sed awk
- Linux进程管理命令
- linux守护进程
- Linux系统下给VMWare安装Tools
- linux系统简单搭建iSCSI
- linux进程通信--信号量
- linux进程通信--消息队列
- linux进程通信--共享内存
- CentOS 7系统挂载NTFS分区的移动硬盘(转载及体验 CentOS6.5系统挂载NTFS分区的移动硬盘)
- Linux服务之DNS(bind)
- Zookeeper linux下使用