标签:多线程
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源)
翻译文章来源: msdn - Multithreading: How to Use the Synchronization Classes
注1: 借助了google翻译和金山词霸
注2: 翻译的不当之处,还请多多指正
在多线程间同步资源是在写多线程时经常遇到的问题。有二个以上的线程来访问同一数据时,经常会导致不可预知的问题。
例如,在同一时间,一个线程在写该数据,而另一个线程在读该数据,这将不知道读线程究竟读出的是什么数据,是老的数据,还是新写入的数据,也或是读出的一部分是老数据、另一部分是新数据。
MFC提供了一些同步和同步控制类来帮助解决这种问题。这篇主题一是阐述这些类,二是阐述如何来使用这些类创建线程安全的典型多线程程序。
Synchronizing resource access between threads is a common problem when writing multithreaded applications. Having two or more threads simultaneously access the same data can lead to undesirable and unpredictable results. For example, one thread could be updating the contents of a structure while another thread is reading the contents of the same structure. It is unknown what data the reading thread will receive: the old data, the newly written data, or possibly a mixture of both. MFC provides a number of synchronization and synchronization access classes to aid in solving this problem. This topic explains the classes available and how to use them to create thread-safe classes in a typical multithreaded application.
一个典型的多线程程序会有一个类来声明资源供多个线程间共享使用。在合理的设计下,线程安全的类不需要调用同步函数,所有的处事都是类的内部,你只需要关注如何使用这个类,而不需要考虑失效的情况。一个创建线程安全类的有效方法是,把同步类整合到资源类中。合并同步类到共享类中是一个较直接的方法。
A typical multithreaded application has a class that represents a resource to be shared among threads. A properly designed, fully thread-safe class does not require you to call any synchronization functions. Everything is handled internally to the class, allowing you to concentrate on how to best use the class, not about how it might get corrupted. An effective technique for creating a fully thread-safe class is to merge the synchronization class into the resource class. Merging the synchronization classes into the shared class is a straightforward process.
其中一个例子,一个程序维护一系列的账户。这个程序允许三个账户在不同的窗口中被检查,但是仅允许在特定的时间进行修改。当账户修改时,修改后的数据通过网络进行数据存档。
As an example, take an application that maintains a linked list of accounts. This application allows up to three accounts to be examined in separate windows, but only one can be updated at any particular time. When an account is updated, the updated data is sent over the network to a data archive.
这个例子需要用到所有的三种同步类,因为它允许三个账户同时被检查,需要使用CSemaphore来进行限制不超过三个可查的;当试图同时查看第四个账户时,程序需要等待其它三个查看账户关闭也或是本次查看失败。当一个账户被修改时,程序使用CCriticalSection来确保在同一时间仅有一个账户被修改,但修改成功后,触发信号CEvent来释放发送信息的线程,这个线程发送新的数据到归档中心。
This example application uses all three types of synchronization classes. Because it allows up to three accounts to be examined at one time, it uses CSemaphore to limit access to three view objects. When an attempt to view a fourth account occurs, the application either waits until one of the first three windows closes or it fails. When an account is updated, the application uses CCriticalSection to ensure that only one account is updated at a time. After the update succeeds, it signals CEvent, which releases a thread waiting for the event to be signaled. This thread sends the new data to the data archive.
设计一个线程安全的类: 如何让一个类做到线程安全,首先添加适当的同步类作为成员变量,放到共享类中。在上个账户管理的例子中,需要添加一个CSemaphore类的成员变量到视图类中,需要添加一个CCriticalSection成员变量到账户链接列表类中,需要添加一个CEvent成员变量到数据存储类中。
Designing a Thread-Safe Class
To make a class fully thread-safe, first add the appropriate synchronization class to the shared classes as a data member. In the previous account-management example, a CSemaphore data member would be added to the view class, a CCriticalSection data member would be added to the linked-list class, and a CEvent data member would be added to the data storage class.
下一步,为所有类中的数据修改或访问资源,添加同步调用;在每个函数中,需要创建CSingleLock或CMultiLock对像并且调用对像的lock方法;当lock的对像出了作用域之后会被销毁,对像的析构函数会完成这个操作,当然,也可以手动调用unlock。
Next, add synchronization calls to all member functions that modify the data in the class or access a controlled resource. In each function, you should create either a CSingleLock or CMultiLock object and call that object‘s Lock function. When the lock object goes out of scope and is destroyed, the object‘s destructor calls Unlock for you, releasing the resource. Of course, you can call Unlock directly if you want.
以这种方式设计出的线程安全类,允许在多线程中轻松的使用,如同使用一个非多线程的类一样,但是却具备较高的安全性。在资源类中封装同步对像和同步访问提供了线程安全的所有优势,并且没有维护同步代码的缺点。
Designing your thread-safe class in this fashion allows it to be used in a multithreaded application as easily as a non-thread-safe class, but with a higher level of safety. Encapsulating the synchronization object and synchronization access object into the resource‘s class provides all the benefits of fully thread-safe programming without the drawback of maintaining synchronization code.
下面的示例代码展示了使用成员变量的方法,在共享资源中类中定义了变量m_CritSection(CCriticalSection类型)和一个CSingleLock对像;共享资源(从CWinThread派生)同步时尝试使用m_CritSection对像的地址创建一个CSingleLock实体,尝试锁定资源,获取到资源之后,在共享对像上完成操作;操作完成后,使用unlock释放资源的锁定。
The following code example demonstrates this method by using a data member, m_CritSection (of type CCriticalSection), declared in the shared resource class and a CSingleLock object. The synchronization of the shared resource (derived from CWinThread) is attempted by creating a CSingleLock object using the address of the m_CritSection object. An attempt is made to lock the resource and, when obtained, work is done on the shared object. When the work is finished, the resource is unlocked with a call to Unlock.
Copy Code
CSingleLock singleLock(&m_CritSection);
singleLock.Lock();
// resource locked
//.usage of shared resource...
singleLock.Unlock();
注意:
CCriticalSection不像其它MFC的同步类,没有超时时间的选项,等待资源被释放的时间将会是无限长的。
Note
CCriticalSection, unlike other MFC synchronization classes, does not have the option of a timed lock request. The waiting period for a thread to become free is infinite.
这种方法的缺点是: 比同样功能却没有添加同步实体的类稍微慢一些;同时,如果存在超过一个线程会删除对像,这种合并的方法可能会工作异常,在这种情况下,最好是分开维护同步对像。
The drawbacks to this approach are that the class will be slightly slower than the same class without the synchronization objects added. Also, if there is a chance that more than one thread might delete the object, the merged approach might not always work. In this situation, it is better to maintain separate synchronization objects.
查找关于如何在不同的情况使用哪种同步类,参考: Multithreading: When to Use the Synchronization Classes
查找更多关于同步的信息,参见平台SDK中的描述,查找关于MFC中对多线程的更多支持,参见Multithreading with C++ and MFC。
For information about determining which synchronization class to use in different situations, see Multithreading: When to Use the Synchronization Classes. For more information about synchronization, see Synchronization in the Platform SDK. For more information about multithreading support in MFC, see Multithreading with C++ and MFC.
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu 转载请标明来源)
Multithreading: How to Use the Synchronization Classes
标签:多线程
原文地址:http://blog.csdn.net/chunyexiyu/article/details/46372725