对于人工重置事件对象,可以同时有多个线程等待到事件对象,成为可调度线程。而对于自动重置的事件对象,等待该事件对象的多个线程只能有一个线程成为可调度线程。
由上我们可以确定:
(1)不管是人工重置的事件对象,还是自动重置的事件对象,等待该事件对象的线程同时可以有多个。也就是说这多个线程都有资格进行等待。这儿不用解释。
(2)前者是多个线程都可成为可调度线程,后者的情况是只能有一个线程可成为可调度线程,这话真是让人看不明白?请详细讲解一下这句话。
4 个解决方案
#1
自动重置 也就是1个线程拿到了,其他线程就拿不到了 这样就只有一个可调度线程
可以打个比方
2家商店 A B,A有很多棒棒糖n个,B只有1个棒棒糖
也就是A是手动,B是自动
A店前面排了很多人,也就是1个1个都能买到棒棒糖,也就是多个线程有机会执行
B店前面也排了很多人,而只有第一个人能买到棒棒糖,而这个人是不确定的,得看系统的调度,所以第一个人拿了以后,其他人就没有机会了买到棒棒糖了,也就是没有执行的机会了...
哈哈 不知道说的恰当不
可以打个比方
2家商店 A B,A有很多棒棒糖n个,B只有1个棒棒糖
也就是A是手动,B是自动
A店前面排了很多人,也就是1个1个都能买到棒棒糖,也就是多个线程有机会执行
B店前面也排了很多人,而只有第一个人能买到棒棒糖,而这个人是不确定的,得看系统的调度,所以第一个人拿了以后,其他人就没有机会了买到棒棒糖了,也就是没有执行的机会了...
哈哈 不知道说的恰当不
#2
《Windows核心编程》读百遍,多线程义自现。
#3
你这个比喻有点疑问,一个事件对象是用来实现线程同步的,怎么可以一个时间片内给多个线程进行使用,那还怎么实现同步呀,这不乱套了?
#4
可调度,就是指,这个线程在内核看来是活跃的,而不是等待事件的状态。
内核的实现非常简单:
伪代码
BOOL
KeSetEvent( struct event_object *event, BOOL f )
{
//// 此处是内核态,上下文保证不用加锁
event->signal = f;
if(f && ! list_empty(&event->wait_threads) ) {
/// 有线程等待这个event
if( event->isManualReset ) {
/// 遍历所有等待的线程,唤醒
while( event->wait_threads.next != &event->wait_threads ) {
struct thread_object *thd;
thd = container_of( event->wait_threads.next, struct thread_object , list );
list_erase(&thd->list);
KeThreadWakeup( thd );
}
} else {
struct thread_object *thd;
/// 取出第一个线程唤醒
thd = container_of( event->wait_threads.next, struct thread_object , list );
list_erase(&thd->list);
KeThreadWakeup( thd );
event->signal = FALSE; /// 信号自动复位
}
}
return TRUE;
}
内核的实现非常简单:
伪代码
BOOL
KeSetEvent( struct event_object *event, BOOL f )
{
//// 此处是内核态,上下文保证不用加锁
event->signal = f;
if(f && ! list_empty(&event->wait_threads) ) {
/// 有线程等待这个event
if( event->isManualReset ) {
/// 遍历所有等待的线程,唤醒
while( event->wait_threads.next != &event->wait_threads ) {
struct thread_object *thd;
thd = container_of( event->wait_threads.next, struct thread_object , list );
list_erase(&thd->list);
KeThreadWakeup( thd );
}
} else {
struct thread_object *thd;
/// 取出第一个线程唤醒
thd = container_of( event->wait_threads.next, struct thread_object , list );
list_erase(&thd->list);
KeThreadWakeup( thd );
event->signal = FALSE; /// 信号自动复位
}
}
return TRUE;
}
#1
自动重置 也就是1个线程拿到了,其他线程就拿不到了 这样就只有一个可调度线程
可以打个比方
2家商店 A B,A有很多棒棒糖n个,B只有1个棒棒糖
也就是A是手动,B是自动
A店前面排了很多人,也就是1个1个都能买到棒棒糖,也就是多个线程有机会执行
B店前面也排了很多人,而只有第一个人能买到棒棒糖,而这个人是不确定的,得看系统的调度,所以第一个人拿了以后,其他人就没有机会了买到棒棒糖了,也就是没有执行的机会了...
哈哈 不知道说的恰当不
可以打个比方
2家商店 A B,A有很多棒棒糖n个,B只有1个棒棒糖
也就是A是手动,B是自动
A店前面排了很多人,也就是1个1个都能买到棒棒糖,也就是多个线程有机会执行
B店前面也排了很多人,而只有第一个人能买到棒棒糖,而这个人是不确定的,得看系统的调度,所以第一个人拿了以后,其他人就没有机会了买到棒棒糖了,也就是没有执行的机会了...
哈哈 不知道说的恰当不
#2
《Windows核心编程》读百遍,多线程义自现。
#3
你这个比喻有点疑问,一个事件对象是用来实现线程同步的,怎么可以一个时间片内给多个线程进行使用,那还怎么实现同步呀,这不乱套了?
#4
可调度,就是指,这个线程在内核看来是活跃的,而不是等待事件的状态。
内核的实现非常简单:
伪代码
BOOL
KeSetEvent( struct event_object *event, BOOL f )
{
//// 此处是内核态,上下文保证不用加锁
event->signal = f;
if(f && ! list_empty(&event->wait_threads) ) {
/// 有线程等待这个event
if( event->isManualReset ) {
/// 遍历所有等待的线程,唤醒
while( event->wait_threads.next != &event->wait_threads ) {
struct thread_object *thd;
thd = container_of( event->wait_threads.next, struct thread_object , list );
list_erase(&thd->list);
KeThreadWakeup( thd );
}
} else {
struct thread_object *thd;
/// 取出第一个线程唤醒
thd = container_of( event->wait_threads.next, struct thread_object , list );
list_erase(&thd->list);
KeThreadWakeup( thd );
event->signal = FALSE; /// 信号自动复位
}
}
return TRUE;
}
内核的实现非常简单:
伪代码
BOOL
KeSetEvent( struct event_object *event, BOOL f )
{
//// 此处是内核态,上下文保证不用加锁
event->signal = f;
if(f && ! list_empty(&event->wait_threads) ) {
/// 有线程等待这个event
if( event->isManualReset ) {
/// 遍历所有等待的线程,唤醒
while( event->wait_threads.next != &event->wait_threads ) {
struct thread_object *thd;
thd = container_of( event->wait_threads.next, struct thread_object , list );
list_erase(&thd->list);
KeThreadWakeup( thd );
}
} else {
struct thread_object *thd;
/// 取出第一个线程唤醒
thd = container_of( event->wait_threads.next, struct thread_object , list );
list_erase(&thd->list);
KeThreadWakeup( thd );
event->signal = FALSE; /// 信号自动复位
}
}
return TRUE;
}