标题:event


事件对象也可以通过通知操作的方式来保持线程的同步。并且可以实现不同进程中的线程同步操作。一个线程通过SetEvent()设置了事件的状态为有标记,将释放任意等待线程。如果事件是手工的,状态标记在调用ResetEvent()后变为无标记;如果事件是自动的,那么在释放了等待线程后就变为了无标记。

下面是一个使用Event事件的多线程实现线程同步的实例:

 

int           tickets=100;

HANDLE   g_hEvent;

 

DWORD WINAPI ThreadProc1(LPVOID lpParameter)

{

while(TRUE)

{

         if(tickets>0)

         {

              Sleep(1);

              tickets--;

         }

         else

         {

              break;

         }

     }

     SetEvent(g_hEvent);

     return 0;

}

 

DWORD WINAPI ThreadProc2(LPVOID lpParameter)

{

     WaitForSingleObject(g_hEvent, INFINITE);

     printf(“%s”, “tickets zero”);

     return 0;

}

 

int main(int argc, char *argv[])

{

 HANDLE hThread1;

 HANDLE hThread2;

 

 g_hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);

 

 hThread1=CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);

 hThread2=CreateThread(NULL,0,ThreadProc2,NULL,0,NULL);

 

 CloseHandle(hThread1);

 CloseHandle(hThread2);

 Sleep(4000);

 CloseHandle(g_hEvent);

 

 return 0;

}


在Linux系统中,是通过condition来定义事件的发生的。

Condition

#include <iostream>

#include <pthread.h>

#include <string>

#include <unistd.h>

 

pthread_mutex_t count_lock;

pthread_cond_t count_nonzero;

unsigned count = 0;

 

decrement_count () {

    pthread_mutex_lock (&count_lock);

    while(count==0)

        pthread_cond_wait( &count_nonzero, &count_lock);

 

    count=count -1;

    pthread_mutex_unlock (&count_lock);

}

increment_count(){

    pthread_mutex_lock(&count_lock);

    if(count==0)

        pthread_cond_signal(&count_nonzero);

    count=count+1;

    pthread_mutex_unlock(&count_lock);

}

 

 

int main(int argc, char* argv[])

{

        pthread_mutex_init(&count_lock, NULL);

        pthread_cond_init(&count_nonzero, NULL);

        pthread_t p1, p2;

        pthread_create(&p1, NULL, decrement_count, NULL);

        pthread_create(&p2, NULL, increment_count, NULL);

}

 

    //pthread_cond_t cond=PTHREAD_COND_INITIALIZER;

    //pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;

 

    一个Condition Variable总是和一个Mutex搭配使用的。一个线程可以调用pthread_cond_wait在一个Condition Variable上阻塞等待,这个函数做以下三步操作:

l         释放Mutex

l         阻塞等待

l         当被唤醒时,重新获得Mutex并返回

pthread_cond_timedwait函数还有一个额外的参数可以设定等待超时,如果到达了abstime所指定的时刻仍然没有别的线程来唤醒当前线程,就返回ETIMEDOUT。一个线程可以调用pthread_cond_signal唤醒在某个Condition Variable上等待的另一个线程,也可以调用pthread_cond_broadcast唤醒在这个Condition Variable上等待的所有线程。

pthread_cond_wait总和一个互斥锁结合使用。在调用pthread_cond_wait前要先获取锁。pthread_cond_wait函数执行时先自动释放指定的锁,然后等待条件变量的变化。在函数调用返回之前,自动将指定的互斥量重新锁住。

int pthread_cond_signal(pthread_cond_t * cond);

pthread_cond_signal通过条件变量cond发送消息,若多个消息在等待,它只唤醒一个。pthread_cond_broadcast可以唤醒所有。调用pthread_cond_signal后要立刻释放互斥锁,因为pthread_cond_wait的最后一步是要将指定的互斥量重新锁住,如果pthread_cond_signal之后没有释放互斥锁,pthread_cond_wait仍然要阻塞。

无论哪种等待方式,都必须和一个互斥锁配合,以防止多个线程同时请求pthread_cond_wait()(或pthread_cond_timedwait(),下同)的竞争条件(Race   Condition)。

pthread_cond_wait() 所做的第一件事就是同时对互斥对象解锁(于是其它线程可以修改已链接列表),并等待条件 mycond 发生。

pthread_cond_wait() 调用还未返回。对互斥对象解锁会立即发生,但等待条件 mycond 通常是一个阻塞操作,这意味着线程将睡眠,在它苏醒之前不会消耗 CPU 周期。为什么要与pthread_mutex 一起使用呢? 这是为了应对 线程1在调用pthread_cond_wait()但线程1还没有进入wait cond的状态的时候,此时线程2调用了 cond_singal 的情况。 如果不用mutex锁的话,这个cond_singal就丢失了。加了锁的情况是,线程2必须等到 mutex 被释放(也就是 pthread_cod_wait() 释放锁并进入wait_cond状态 ,此时线程2上锁) 的时候才能调用cond_singal



看文字不过瘾?点击我,进入周哥教IT视频教学
麦洛科菲长期致力于IT安全技术的推广与普及,我们更专业!我们的学员已经广泛就职于BAT360等各大IT互联网公司。详情请参考我们的 业界反馈 《周哥教IT.C语言深学活用》视频

我们的微信公众号,敬请关注