事件对象也可以通过通知操作的方式来保持线程的同步。并且可以实现不同进程中的线程同步操作。一个线程通过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;
}
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。
Copyright 2011-2020 © MallocFree. All rights reserved.