关于多线程控制的几个小问题

时间:2022-12-28 17:31:36
如下关于使用事件对象实现线程同步的描述中:

    对于人工重置事件对象,可以同时有多个线程等待到事件对象,成为可调度线程。而对于自动重置的事件对象,等待该事件对象的多个线程只能有一个线程成为可调度线程。
    
    由上我们可以确定:
    (1)不管是人工重置的事件对象,还是自动重置的事件对象,等待该事件对象的线程同时可以有多个。也就是说这多个线程都有资格进行等待。这儿不用解释。

    (2)前者是多个线程都可成为可调度线程,后者的情况是只能有一个线程可成为可调度线程,这话真是让人看不明白?请详细讲解一下这句话。

4 个解决方案

#1


自动重置  也就是1个线程拿到了,其他线程就拿不到了  这样就只有一个可调度线程


可以打个比方

2家商店 A  B,A有很多棒棒糖n个,B只有1个棒棒糖

也就是A是手动,B是自动

A店前面排了很多人,也就是1个1个都能买到棒棒糖,也就是多个线程有机会执行

B店前面也排了很多人,而只有第一个人能买到棒棒糖,而这个人是不确定的,得看系统的调度,所以第一个人拿了以后,其他人就没有机会了买到棒棒糖了,也就是没有执行的机会了...

哈哈  不知道说的恰当不 关于多线程控制的几个小问题

#2


《Windows核心编程》读百遍,多线程义自现。

#3


引用 1 楼 xihu1364 的回复:
自动重置  也就是1个线程拿到了,其他线程就拿不到了  这样就只有一个可调度线程


可以打个比方

2家商店 A  B,A有很多棒棒糖n个,B只有1个棒棒糖

也就是A是手动,B是自动

A店前面排了很多人,也就是1个1个都能买到棒棒糖,也就是多个线程有机会执行

B店前面也排了很多人,而只有第一个人能买到棒棒糖,而这个人是不确定的,得看系统的调度,所以第一个人拿了以后,其他人就没有机会了买到棒棒糖了,也就是没有执行的机会了...

哈哈  不知道说的恰当不 关于多线程控制的几个小问题


你这个比喻有点疑问,一个事件对象是用来实现线程同步的,怎么可以一个时间片内给多个线程进行使用,那还怎么实现同步呀,这不乱套了?

#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;
}

#1


自动重置  也就是1个线程拿到了,其他线程就拿不到了  这样就只有一个可调度线程


可以打个比方

2家商店 A  B,A有很多棒棒糖n个,B只有1个棒棒糖

也就是A是手动,B是自动

A店前面排了很多人,也就是1个1个都能买到棒棒糖,也就是多个线程有机会执行

B店前面也排了很多人,而只有第一个人能买到棒棒糖,而这个人是不确定的,得看系统的调度,所以第一个人拿了以后,其他人就没有机会了买到棒棒糖了,也就是没有执行的机会了...

哈哈  不知道说的恰当不 关于多线程控制的几个小问题

#2


《Windows核心编程》读百遍,多线程义自现。

#3


引用 1 楼 xihu1364 的回复:
自动重置  也就是1个线程拿到了,其他线程就拿不到了  这样就只有一个可调度线程


可以打个比方

2家商店 A  B,A有很多棒棒糖n个,B只有1个棒棒糖

也就是A是手动,B是自动

A店前面排了很多人,也就是1个1个都能买到棒棒糖,也就是多个线程有机会执行

B店前面也排了很多人,而只有第一个人能买到棒棒糖,而这个人是不确定的,得看系统的调度,所以第一个人拿了以后,其他人就没有机会了买到棒棒糖了,也就是没有执行的机会了...

哈哈  不知道说的恰当不 关于多线程控制的几个小问题


你这个比喻有点疑问,一个事件对象是用来实现线程同步的,怎么可以一个时间片内给多个线程进行使用,那还怎么实现同步呀,这不乱套了?

#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;
}