线程与进程的区别:
(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销
Linux进程间通讯
(1)管道(Pipe):管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信。(2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关 系 进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。
(3)信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送 信号给进程本身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数)。
(4)消息(Message)队列:消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字节流以及缓冲区大小受限等缺
(5)共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
(6)内存映射(mapped memory):内存映射允许任何多个进程间通信,每一个使用该机制的进程通过把一个共享的文件映射到自己的进程地址空间来实现它。
(7)信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
(8)套接口(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
IPC比较
1.管道:速度慢,容量有限,只有父子进程能通讯
2.FIFO:任何进程间都能通讯,但速度慢
3.消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题
4.信号量:不能传递复杂消息,只能用来同步
5.共享内存:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全(全局变量和静态变量引起),当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存
2.0 线程同步方法
- 临界区:通过对多线程串行化来访问公共资源或一段代码,速度快,适合控制数据访问
- 互斥量:为协调共同对一个共享资源的单独访问而设计的.
- 信号量:为控制一个具有有限数量用户资源而设计.
- 事件对象:用来通知线程有一些事件已发生,从而启动后继任务的开始.
-
1、 事件对象(Event)
用事件(Event)来同步线程是最具弹性的了. 一个事件有两种状态:激发状态和未激发状态. 也称有信号状态和无信号状态. 事件又分两种类型:手动重置事件和自动重置事件. 手动重置事件被设置为激发状态后,会唤醒所有等待的线程,而且一直保持为激发状态,直到程序重新把它设置为未激发状态. 自动重置事件被设置为激发状态后,会唤醒“一个”等待中的线程,然后自动恢复为未激发状态. 所以用自动重置事件来同步两个线程比较理想.
2、 临界区(Critical Section)
使用临界区域的第一个忠告就是不要长时间锁住一份资源. 但进入临界区后必须尽快地离开,释放资源. 如果不释放的话,会如何?答案是不会怎样. 临界区域的一个缺点就是:Critical Section不是一个核心对象,无法获知进入临界区的线程是生是死,如果进入临界区的线程挂了,没有释放临界资源,系统无法获知,而且没有办法释放该临界资源. 这个缺点在互斥器(Mutex)中得到了弥补.3、 互斥量(Mutex)
互斥器的功能和临界区域很相似. 区别是:Mutex所花费的时间比Critical Section多的多,但是Mutex是核心对象(Event、Semaphore也是),可以跨进程使用,而且等待一个被锁住的Mutex可以设定TIMEOUT,不会像Critical Section那样无法得知临界区域的情况,而一直死等.4、 信号量(Semaphore)
信号量是最具历史的同步机制. 信号量是解决producer/consumer问题的关键要素.
1、 临界区(CCriticalSection) 当多个线程访问一个独占性共享资源时,可以使用临界区对象。拥有临界区的线程可以访问被保护起来的资源或代码段,其他线程若想访问,则被挂起,直到拥有临界区的线程放弃临界区为止。具体应用方式: 1、 定义临界区对象CcriticalSection g_CriticalSection; 2、 在访问共享资源(代码或变量)之前,先获得临界区对象,g_CriticalSection.Lock(); 3、 访问共享资源后,则放弃临界区对象,g_CriticalSection.Unlock(); 2、 事件(CEvent) 事件机制,则允许一个线程在处理完一个任务后,主动唤醒另外一个线程执行任务。比如在某些网络应用程序中,一个线程如A负责侦听通信端口,另外一个线程B负责更新用户数据,利用事件机制,则线程A可以通知线程B何时更新用户数据。每个Cevent对象可以有两种状态:有信号状态和无信号状态。Cevent类对象有两种类型:人工事件和自动事件。
3、 互斥量(CMutex) 互斥对象和临界区对象非常相似,只是其允许在进程间使用,而临界区只限制与同一进程的各个线程之间使用, 但是更节省资源,更有效率。 4、 信号量(CSemphore) 当需要一个计数器来限制可以使用某共享资源的线程数目时,可以使用“信号量”对象。CSemaphore类对象保存了对当前访问某一个指定资源的线程的计数值,该计数值是当前还可以使用该资源的线程数目。如果这个计数达到了零,则所有对这个CSemaphore类对象所控制的资源的访问尝试都被放入到一个队列中等待,直到超时或计数值不为零为止。
3.0线程通信
1.全局变量
进程中的线程间内存共享,这是比较常用的通信方式和交互方式.
注:定义全局变量时最好使用volatile来定义,以防编译器对此变量进行优化.
2.Message消息机制
常用的Message通信的接口主要有两个:PostMessage和PostThreadMessage,
PostMessage为线程向主窗口发送消息. 而PostThreadMessage是任意两个线程之间的通信接口.
3.事件对象(CEvent对象)
http://www.cnblogs.com/fora/archive/2011/05/06/2039511.html
同步与互斥:简单的控制
通信:交互的信息更多
Windows和Linux下用于同步与通信的机制大体一致,下面简单做一个归纳。
1.多线程的同步
方式 Windows Linux 备注
原子操作 有 有 速度快
互斥锁 临界区和Mutex pthread_mutex_t 此外还有自旋锁,读写锁等扩展,用于互斥,保证一个时刻只有一个线程执行
条件变量 Event pthread_cond_t 用于同步。
信号量 Semaphore sem_t 用于控制资源的访问
2.多进程的同步
方式 Windows Linux
互斥锁 Mutex pthread_mutex_t
条件变量 Event pthread_cond_t
信号量 Semaphore sem_t
多进程的同步方式与多线程的同步方式基本一致,除了不能使用原子操作外;另外对于同步对象的创建方式上稍有差异。
3.多进程的通信
方式 Windows Linux
信号 无 异步的通信机制
共享内存 有 有
匿名管道 有 有
命名管道/FIFO 有 有
消息队列 有 有
套接字 有 有
http://blog.chinaunix.net/uid-27411029-id-4131123.html
http://blog.youkuaiyun.com/neustar1/article/details/7489406