1、解释python
线程之间通讯的两个基本问题是互斥和同步。windows
线程同步是指:线程之间所具备的一种制约关系,一个线程的执行依赖另外一个线程的消息,当它没有获得另外一个线程的消息时,应该等待,直到消息到达时才被唤醒。多线程
线程互斥是指:对于共享的操做系统资源(指的是广义的“资源”,而不是Windows.res文件,譬如全局变量就是一种共享资源),在各线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任什么时候刻最多只容许一个线程去使用,其余要使用该资源的线程必须等待,直到占用资源者释放该资源。ide
线程互斥是一种特殊的线程同步。函数
实际上,互斥和同步对应着线程间通讯发生的两种状况:性能
(1) 当有多个线程访问共享资源而不使资源被破坏时;spa
(2) 当一个线程须要将某个任务已经完成的状况通知另外一个或多个线程时。操作系统
2、在windows32中,同步机制主要有如下几种:线程
(1) 事件(Event);3d
(2)信号量(semaphore);
(3)互斥量(mutex);
(4)临界区(Critical, section)
全局变量
由于进程中的全部线程都可以访问全部的全局变量,于是全局变量成为Win32多线程通讯的最简单方式。
事件
事件(Event)是WIN32提供的最灵活的线程间同步方式,事件能够处于激发状态(signaled or true) 或未激发状态(unsignal or False)。根据状态变迁方式的不一样,事件可分为两类:
(1) 手动设置:这种对象只可能用程序手动设置,在须要该事件或者事件发生时,采用SetEvent及ResetEvent来进行设置。
(2) 自动恢复: 一旦事件发生并被处理后,自动恢复到没有事件状态,不须要再次设置。
例子:
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import threading 5 import time 6 7 8 def func(): 9 # 线程之间的通讯,能够用事件去实现 10 # 建立一个事件对象 11 event = threading.Event() 12 13 def run(): 14 for i in range(5): 15 # wait:阻塞,等待事件的触发 16 event.wait() 17 # clear(): 重置,使上面的wait重置到阻塞状态。 18 event.clear() 19 print('sunck is a good man! %d' % i) 20 21 t = threading.Thread(target=run).start() 22 return event 23 24 25 e = func() 26 # 触发事件 27 for i in range(5): 28 time.sleep(2) 29 # 设置事件 30 e.set()
使用“事件”机制应该注意如下事项:
(1) 若是跨进程访问事件,必须对事件命名,在对事件命名的时候,要注意不要与系统命名空间中的其它全局命名对象冲突;
(2) 事件是否要自动恢复;
(3) 事件的初始状态设置。
因为event对象属于内核对象,故进程B能够调用OpenEvent函数经过对象的名字得到进程A中event对象的句柄,而后将这个句柄用于ResetEvent、SetEvent和WaitForMultipleObjects等函数中。此法能够实现一个进程的线程控制另外一进程中线程的运行。
临界区
定义临界区变量
一般状况下,CRITICAL_SECTION结构体应该被定义为全局变量,以便于进程中的全部线程方便地按照变量名来引用该结构体。
关于临界区的使用,有下列注意点:
(1)每一个共享资源使用一个CRITICAL_SECTION变量;
(2)不要长时间运行关键代码段,当一个关键代码段长时间运行时,其余线程就会进入等待状态,这会下降应用程序的运行性能;
(3)若是须要同时访问多个资源,则可能连续调用EnterCriticalSection;
(4)Critical Section不是OS核心对象,若是进入临界区的线程"挂"了,将没法释放临界资源。这个缺点在Mutex中获得了弥补。
互斥
互斥量的做用是保证每次只能有一个线程得到互斥量而得以继续执行,使用CreateMutex函数建立,Mutex是核心对象,能够跨进程访问。
互斥(mutex)内核对象可以确保线程拥有对单个资源的互斥访问权。互斥对象的行为特性与临界区相同,可是互斥对象属于内核对象,而临界区则属于用户方式对象,所以这致使mutex与Critical Section的以下不一样: (1) 互斥对象的运行速度比关键代码段要慢; (2) 不一样进程中的多个线程可以访问单个互斥对象; (3) 线程在等待访问资源时能够设定一个超时值。