您的位置:首页 > 运维架构 > Linux

linux进程和线程之间通信方法和同步方法总结

2015-12-18 21:43 761 查看

进程和线程之间的通信方法

一:进程之间的通信方法

1.消息队列

2.共享内存

3.管道:分为匿名管道用在父子进程之间通信,命名管道用于父子进程或不相关进程之间通信;

参考:linux进程间通信-----管道总结实例

4.父子进程也可以通过文件描述符通信,共同打开同一个文件;

二:线程之间的通信方法

1.全局数据,全局变量,全局数据结构

2.创建线程的时候通过参数arg主线程传递数据给新线程 pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

新线程退出的时候通过void pthread_exit(void *retval);和int pthread_join(pthread_t thread, void **retval);向主线程传递信息;

见博客:多线程函数系列pthread_create(), pthread_join(), pthread_self(),pthread_exit(), pthread_detach()实例详解

3.文件句柄,多个线程共享文件

待续。。。这部分还要写。。。

进程和线程之间的同步方法

1:信号量

一般是0和1两个值,进去临界区减去1(P操作),离开临界区加上1(V操作);如果涉及到对多个资源进行控制,那么信号量的值设置为资源的数目;

2:互斥量

互斥量其实是信号量的一种;每当一个线程或进程访问临界区的时候就要先获取互斥量,离开临界区的时候释放互斥量;如果获取互斥量失败,则阻塞;所以互斥量使多个线程或进程对临界区的执行串行化;

见博客:linux程序多线程互斥锁的简单使用

对互斥量进行操作的主要API

#include <pthread.h>
pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t recmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
pthread_mutex_t errchkmutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);//初始化该互斥锁
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);//销毁该互斥锁

#include <pthread.h>
#include <time.h>
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,const struct timespec *restrict abs_timeout);

对互斥量的属性进行操作的主要API

#include <pthread.h>
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind);
int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind);

int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict attr, int *restrict pshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,int pshared);//设置互斥量的属性;当pshared是PTHREAD_PROCESS_SHARED允许不同进程的线程使用互斥量;
//当pshared是PTHREAD_PROCESS_PRIVATE仅仅允许相同进程的线程使用互斥量;

2:读-写锁

当多个线程对共享内存进行操作的时候就要控制它们了,否则很容易对共享内存的数据访问发生竞争;

可以允许多个线程同时对共享内存进行读取(因为它不改变共享内存的内容),它们可以拥有用于读取的读-写锁;但是任意时刻只允许一个线程对共享内存进行写入或更改;
其实我们为了控制这种写入的竞争发生,也可以使用互斥量来控制;但是有一个问题。。。如果使用互斥量的话,那么每个时刻只能有一个线程对共享内存进行读或写;

但是我们想让多个线程同时对共享内存进行读取,这样的话使用互斥量就有点效率低下了。这时我们应该使用读-写锁;

备注:我们会发现对互斥量只有一个加锁请求,但是对读-写锁有两个加锁请求;

初始化/销毁读-写锁

#include <pthread.h>
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);//销毁读-写锁
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);//初始化读-写锁

请求占有/尝试请求读锁

#include <pthread.h>
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);//请求获得一个读锁,如果没有其它线程持有写锁,则会得到读锁;但是有其它线程持有写锁,则该线程会阻塞;
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);//请求获得一个读锁,如果没有其它线程持有写锁,则会得到读锁;但是有其它线程持///有写锁,则返回,不阻塞;

请求占有/尝试请求写锁

#include <pthread.h>
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);//请求获得一个写锁,如果有其它线程持有读锁或写锁,则返回,不阻塞;
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);//请求获得一个写锁,只有在没有其它线程持有读锁或写锁的情况下才会得到写锁,否则该线程会阻塞;

定时请求读锁

#include <pthread.h>
#include <time.h>
int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock,const struct timespec *restrict abs_timeout);//请求读锁,如果失败会阻塞,但是只会阻塞abs_timeout长时间

定时请求写锁

#include <pthread.h>
#include <time.h>
int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock,const struct timespec *restrict abs_timeout);//请求写锁,如果失败会阻塞,但是只会阻塞abs_timeout长时间

初始化/销毁/设置/得到读-写锁的属性对象

#include <pthread.h>
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);//销毁读-写锁的属性对象
int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);//初始化读-写锁的属性对象

int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *restrict attr, int *restrict pshared);//得到属性
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr,int pshared);//设置属性;当pshared是PTHREAD_PROCESS_SHARED允许不同进程的线程使用读-写锁;
//当pshared是PTHREAD_PROCESS_PRIVATE仅仅允许相同进程的线程使用读-写锁;

3:条件变量

具体实例介绍见博客:Linux多线程消费者和生产者模型实例(互斥锁和条件变量使用)

条件变量和互斥量在一起使用;

比如当我们使用请求互斥量的时候,如果请求失败会阻塞;

如果有情况是获得了互斥锁,但是条件不满足,不能继续执行,此时只能等待。。。。这个时候就要用到条件变量了。因为如果我们一直等待的话,那么其它线程就不能获得该锁;此时有可能进入死锁状态;

解决办法,此时应该调用pthread_cond_wait(&g_cond, &g_mutex),让互斥锁g_mutex在这个g_cond条件上等待;

线程调用pthread_cond_wait这个函数之后,内核会做下面这些事:

1,拿到锁的线程,把锁暂时释放;

2,线程休眠,进行等待;

3,线程等待通知,要醒来。(重新获取锁)

线程库将上面三步做成了原子性操作;和Linux内核绑定在一起;

其它线程在条件满足的时候调用pthread_cond_signal(&g_cond);向这个条件变量g_cond上发送一个信号,表示条件满足;

如果条件满足,那么刚才因为调用pthread_cond_wait而等待的线程会醒来(重新获取锁,再次判断条件是否满足);如果条件满足,然后在临界区进行操作,最后解锁,离开临界区;

//下面是man手册对pthread_cond_wait的介绍:pthread_cond_wait atomically unlocks the mutex (as per pthread_unlock_mutex) and waits for the condition variable cond to be signaled. The thread execution is

suspended and does not consume any CPU time until the condition variable is signaled. The mutex must be locked by the calling thread on entrance to pthread_cond_wait.

Before returning to the calling thread, pthread_cond_wait re-acquires mutex (as per pthread_lock_mutex)

对条件变量操作的主要API

#include <pthread.h>
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//条件变量静态初始化
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);//条件变量初始化
int pthread_cond_signal(pthread_cond_t *cond);//向这个条件变量g_cond上发送一个信号,表示条件满足;
int pthread_cond_broadcast(pthread_cond_t *cond);//向这个条件变量g_cond上发送一个信号,表示条件满足;
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);//让互斥锁g_mutex在这个g_cond条件上等待;
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);让互斥锁g_mutex在这个g_cond条件上等待abstime秒;
int pthread_cond_destroy(pthread_cond_t *cond);//销毁条件变量

对条件变量属性操作的主要API

#include <pthread.h>
int pthread_condattr_init(pthread_condattr_t *attr);//初始化条件变量属性对象
int pthread_condattr_destroy(pthread_condattr_t *attr);//销毁条件变量属性对象
int pthread_condattr_getpshared(const pthread_condattr_t *restrict attr,int *restrict pshared);//获得条件变量的属性
int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared);//设置条件变量的属性;当pshared是PTHREAD_PROCESS_SHARED允许不同进程的线程使用条件变量;
//当pshared是PTHREAD_PROCESS_PRIVATE仅仅允许相同进程的线程使用条件变量;

int pthread_condattr_getclock(const pthread_condattr_t *restrict attr, clockid_t *restrict clock_id);//得到属性和超时服务时钟clock_id,默认是系统时钟
int pthread_condattr_setclock(pthread_condattr_t *attr, clockid_t clock_id);//设置属性和超时服务时钟clock_id,默认是系统时钟
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: