003、数据(线程)同步
数据(线程)同步的方法:
1、原子操作
它表示在多个线程访问同一个全局资源的时候,能够确保所有其他的线程都不在同一时间内访问相同的资源。也就是他确保了在同一时刻只有唯一的线程对这个资源进行访问。这有点类似互斥对象对共享资源的访问的保护,但是原子操作更加接近底层,因而效率更高。
2:事件(Event)主要用来线程间的等待通知
事件能够通知一个操作已经完成。有两种不同类型的事件对象。一种是人工重置的事件,另一种是自动重置的事件。当人工重置的事件得到通知时,等待该事件的所有线程均变为可调度线程。当一个自动重置的事件得到通知时,等待该事件的线程中只有一个线程变为可调度线程。
Microsoft 为自动重置的事件定义了应该成功等待的副作用规则,即当线程成功地等待到该对象时,自动重置的事件就会自动重置到未通知状态。这就是自动重置的事件如何获 得它们的名字的方法。通常没有必要为自动重置的事件调用ResetEvent函数,因为系统会自动对事件进行重置。但是,Microsoft没有为人工重 置的事件定义成功等待的副作用,所以需要调用ResetEvent()。
Event API:
CreateEvent:Creates or opens a named or unnamed event object
//创建或打开一个命名的或无名的事件对象
CreateEventEx:Creates or opens a named or unnamed event object and returns a handle to the object.
//创建或打开一个命名的或无名的事件对象并返回一个对象的句柄。
OpenEvent:Opens an existing named event object.
//打开一个现有的命名的事件对象
PulseEvent:Sets the specified event object to the signaled state and then resets it to he nonsignaled state after releasing the appropriate number of waiting threads.
//将指定的事件对象设置为有信号状态,然后重置后到nonsignaled状态释放 适当的等待线程的数量。
ResetEvent:Sets the specified event object to the nonsignaled state.
//将指定的事件对象设置成有信号状态。
SetEvent:Sets the specified event object to the signaled state.
//将指定的时间对象设置成有信号状态
003、CRITICAL_SECTION(临界区)
临界区在使用时以CRITICAL_SECTION结构对象保护共享资源,并分别用EnterCriticalSection()和LeaveCriticalSection()函数去标识和释放一个临界区。所用到的CRITICAL_SECTION结构对象必须经过InitializeCriticalSection()的初始化后才能使用,而且必须确保所有线程中的任何试图访问此共享资源的代码都处在此临界区的保护之下。否则临界区将不会起到应有的作用,共享资源依然有被破坏的可能。
// 临界区结构对象
CRITICAL_SECTION g_cs;
// 初始化临界区
InitializeCriticalSection(&g_cs);
// 进入临界区
EnterCriticalSection(&g_cs);
// 对共享资源进行写入操作
/*****************************************/
// 离开临界区
LeaveCriticalSection(&g_cs);
不论是硬件临界资源,还是软件临界资源,多个线程必须互斥地对它进行访问。每个线程中访问临界资源的那段代码称为临界区(Critical Section)。
每个线程中访问临界资源的那段程序称为临界区(Critical Section)(临界资源是一次仅允许一个线程使用的共享资源)。每次只准许一个线程进入临界区,进入后不允许其他线程进入。不论是硬件临界资源,还是软件临界资源,多个线程必须互斥地对它进行访问。
多个线程中涉及到同一个临界资源的临界区称为相关临界区。
线程进入临界区的调度原则是: ①如果有若干线程要求进入空闲的临界区,一次仅允许一个线程进入。②任何时候,处于临界区内的线程不可多于一个。如已有线程进入自己的临界区,则其它所有试图进入临界区的线程必须等待。③进入临界区的线程要在有限时间内退出,以便其它线程能及时进入自己的临界区。④如果线程不能进入自己的临界区,则应让出CPU,避免线程出现"忙等"现象。
如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。