任务:实现三路视频的任意回放
要求:使用线程控制回放,回放方式可选择
2006
年
10
月
22
日
星期日
问题
:在两路或三路同时回放同一个文件夹下的
BMP
图像时,
由于两个或三个线程同时访问相同的数据而引发冲突,使线程意外终止。
解决方法:
利用MFC提供的
同步类和同步访问类。
同步类:
CSyncObject, CSemaphore, CMutex, CCriticalSection ,CEvent
;
同步类用于当访问资源时保证资源的整体性。其中
CsyncObject
是其它四个同步类的基类,不直接使用。信号同步类
CSemaphore
通常用于当一个应用程序中同时有多个线程访问一个资源(例如,应用程序允许对同一个
Document
有多个
View
)的情况;事件同步类
CEvent
通常用于在应用程序访问资源之前应用程序必须等待(比如,在数据写进一个文件之前数据必须从通信端口得到)的情况;而对于互斥同步类
CMutex
和临界区同步类
CcriticalSection
都是用于保证一个资源一次只能有一个线程访问,二者的不同之处在于前者允许有多个应用程序使用该资源(例如,该资源在一个
DLL
当中)而后者则不允许对同一个资源的访问超出进程的范畴,而且使用临界区的方式效率比较高。
同步访问类:
CMultiLock
和
CSingleLock
。
同步访问类用于获得对这些控制资源的访问。
CMultiLock
和
CSingleLock
的区别仅在于是需要控制访问多个还是单个资源对象。
本问题可以使用互斥同步类
CMutex
、
信号量
同步类
CSemaphore
和临界区同步类
CcriticalSection
中的任意一个解决。
1
、
临界区
临界区是保证在某一个时间只有一个线程可以访问数据的方法。使用它的过程中,需要给各个线程提供一个共享的临界区对象,无论哪个线程占有临界区对象,都可以访问受到保护的数据,这时候其它的线程需要等待,直到该线程释放临界区对象为止,临界区被释放后,另外的线程可以强占这个临界区,以便访问共享的数据。
当利用临界区同步时,同一时刻每次只有一个线程可以
访问受到保护的数据
,这样可以保证程序的稳定性。由于当一个线程
访问受到保护的数据
的时候,其他线程必须等待,所以同步时耗时也较多。
#include "afxmt.h"
CCriticalSection Section;//
声明一个临界区
同步类
对象
当线程需要访问保护数据时,调用临界区对象的
Lock()
成员函数;当对保护数据的操作完成之后,调用临界区对象的
Unlock()
成员函数释放对临界区对象的拥有权,以使另一个线程可以夺取临界区对象并访问受保护的数据。
2
.
互斥
互斥跟临界区很相似,便远比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。通过
互斥同步类
CMutex
来完成线程间的互斥,为了访问一个互斥对象,务必建立一个
同步访问类
CSingleLock
或
CMultiLock
对象,用于访问控制。使用方法:
#include "afxmt.h"
CMutex m_mutex;
//
声明一个互斥
同步类
对象
在线程执行函数中声明
同步访问类
CSingleLock
对象
CSingleLock slock(&m_mutex);
如果互斥没有被线程占用,那么当前的调用线程可以成为互斥的占用者。要实现对互斥的访问,就要调用
CSingleLock
的成员函数
Lock()
,如果一个线程占用了互斥,那么系统将挂起当前的调用线程,直到这个互斥被释放为止,这时,被挂起的线程将被唤醒并取得对互斥的控制。释放互斥是通过调用
CSingleLock
的成员函数
UnLock()
来实现的。
3
.信号量
信号量的用法和互斥的用法很相似,不同的是它可以同一时刻允许多个线程访问同一个资源,创建一个信号量需要用
Csemaphore
类声明一个对象,一旦创建了一个信号量对象,就可以用它来对资源的访问技术。要实现计数处理,先创建一个
CsingleLock
或
CmltiLock
对象,然后用该对象的
Lock()
函数减少这个信号量的计数值,
Unlock()
反之。
本任务中采用临界区
同步类。