本论坛为只读模式,仅供查阅,不能注册新用户,不能发帖/回帖,有问题可发邮件 xikug.xp (^) gmail.com
查看: 3871|回复: 6

公布技术挑战第一题答案 [复制链接]

Rank: 3Rank: 3

发表于 2011-6-6 13:39:49 |显示全部楼层
该题只有mszjk给全了2种解法,可参考其答案。
这道题其实是一道线程池线程同步题。目标2需要利用timer特性创建16个线程并做线程同步,打印haha。
注意createtimerqueuetimer的最后一个参数,MSDN有如下说明:
----------------------------------------------------------------------------------------------------------------------
WT_EXECUTELONGFUNCTION :
The callback function can perform a long wait. This flag helps the system to decide if it should create a new thread.
----------------------------------------------------------------------------------------------------------------------
设置了该标志(0x10)后,系统会“决定”何时创建一个新的线程。对于定时器来说,很显然该“新”线程应该是在一个callback超时时建立。对于该题目来说,由于callback每秒中调用一次,如果在callback中有Sleep(N)(N>1000),则系统会创建新的线程。下面看第一个问:

1. 蛋疼:以16s和4s间隔打印1个"haha\n",该问有几种做法,很多人采用计数器的形式,维护一个static变量,只在第16s,20s,36s...打印haha,其他时间点不打印,该解法没问题。
   陷阱:如果callback中用到了Sleep函数,并且没有做线程同步的话,很显然就错了。

2. 该问也有几种解法(假设第一次进入callback时开始计时为第0s)
a. Sleep变长时间:第0s的callback中Sleep(16000),这将导致第1s时一个新线程建立并调用callback,在这个callback中Sleep(15000),下一个callback中Sleep(14000)...直到第16s进入callback时一齐打出16个haha。4s情况类此。注意static变量在不同线程间的传递问题,一定要先自增。
b. 做线程同步:可用event或者cs等对象,道理都是相同的。参考答案给出一种cs的解法。即第0s回调函数中取锁并Sleep(16000),接下来的15个线程全部等待取锁,直到第一个线程释放锁,16个线程一齐打印haha。4s情况类此。event对象类此。

目标2参考答案:
static int i,j,k = 0;
        static CRITICAL_SECTION cs;
        if (i == 0)
        {
                InitializeCriticalSection(&cs);
        }
       
        i++;
        printf("current i: %d current threadid: %d\n", i, GetCurrentThreadId());
        EnterCriticalSection(&cs);

        if (i == 1 || i == j)
        {
                j = i + 20;
                Sleep(16000);
               
        }
        else if (i == 17 || i == k)
        {
                k = i + 20;
                Sleep(4000);
        }
       
        printf("haha\n");
        LeaveCriticalSection(&cs);

Rank: 1

发表于 2011-6-6 17:52:16 |显示全部楼层
这也是针对系统不是很忙的时候吧,如果sleep完刚好有更高优先级的线程交付时是不是会引起一些误差呢?

Rank: 1

发表于 2011-6-7 01:23:36 |显示全部楼层
[quote=\"majinxin2003\"]这也是针对系统不是很忙的时候吧,如果sleep完刚好有更高优先级的线程交付时是不是会引起一些误差呢?[/quote]
要是这么说的话,如果有一个线程的优先级无限大(事实上这应是不可能的,只是这个例子解释起来方便),以至于系统没有剩余的CPU时间分给其他的,那就会无限误差,但是测试用的计时器也停了,所以相对于程序自身是没有误差的?

P.S.:对于每一个观察者不存在一种让所有人都认同的时间,时间是相对的[详见某霍金XX简史等相关书籍]

Rank: 3Rank: 3

发表于 2011-6-7 05:30:25 |显示全部楼层
[quote=\"KiAcler\"][quote=\"majinxin2003\"]这也是针对系统不是很忙的时候吧,如果sleep完刚好有更高优先级的线程交付时是不是会引起一些误差呢?[/quote]
要是这么说的话,如果有一个线程的优先级无限大(事实上这应是不可能的,只是这个例子解释起来方便),以至于系统没有剩余的CPU时间分给其他的,那就会无限误差,但是测试用的计时器也停了,所以相对于程序自身是没有误差的?

P.S.:对于每一个观察者不存在一种让所有人都认同的时间,时间是相对的[详见某霍金XX简史等相关书籍][/quote]
不能这么解释吧,2l说的意思是等待之后有高优先级别的线程抢先导致callback无法定时调用的问题。实际上确实有这种极端的情况出现的概率。

Rank: 1

发表于 2011-6-8 13:04:33 |显示全部楼层
[quote=\"Azy\"][quote=\"KiAcler\"][quote=\"majinxin2003\"]这也是针对系统不是很忙的时候吧,如果sleep完刚好有更高优先级的线程交付时是不是会引起一些误差呢?[/quote]
要是这么说的话,如果有一个线程的优先级无限大(事实上这应是不可能的,只是这个例子解释起来方便),以至于系统没有剩余的CPU时间分给其他的,那就会无限误差,但是测试用的计时器也停了,所以相对于程序自身是没有误差的?

P.S.:对于每一个观察者不存在一种让所有人都认同的时间,时间是相对的[详见某霍金XX简史等相关书籍][/quote]
不能这么解释吧,2l说的意思是等待之后有高优先级别的线程抢先导致callback无法定时调用的问题。实际上确实有这种极端的情况出现的概率。[/quote]

是的,分时系统做到精确调度确实不太靠谱,实时系统的话会好很多,一切按计划进行~

Rank: 3Rank: 3

发表于 2011-6-8 14:16:39 |显示全部楼层
[quote=\"majinxin2003\"][quote=\"Azy\"][quote=\"KiAcler\"][quote=\"majinxin2003\"]这也是针对系统不是很忙的时候吧,如果sleep完刚好有更高优先级的线程交付时是不是会引起一些误差呢?[/quote]
要是这么说的话,如果有一个线程的优先级无限大(事实上这应是不可能的,只是这个例子解释起来方便),以至于系统没有剩余的CPU时间分给其他的,那就会无限误差,但是测试用的计时器也停了,所以相对于程序自身是没有误差的?

P.S.:对于每一个观察者不存在一种让所有人都认同的时间,时间是相对的[详见某霍金XX简史等相关书籍][/quote]
不能这么解释吧,2l说的意思是等待之后有高优先级别的线程抢先导致callback无法定时调用的问题。实际上确实有这种极端的情况出现的概率。[/quote]

是的,分时系统做到精确调度确实不太靠谱,实时系统的话会好很多,一切按计划进行~

[/quote]
除非人为的故意阻塞,否则Sleep函数返回之后线程还是会比较准时的得到调度的,因为
1. 工作在实时级别的内核线程知道自己在干什么,从来不会强制霸占CPU过长时间,而CPU时间基本上都是idle进程占用的
2. 多核处理器可以均衡和调和线程的调度(还有诸如超线程机制)
3. windows内核可以通过某种机制来提升饥饿线程的当前优先级以保证其不会太过饥饿

Rank: 2

发表于 2011-6-8 16:31:31 |显示全部楼层
Sleep居然可以让timer重新生成线程,学习了
您需要登录后才可以回帖 登录 | 立即加入

Archiver|手机版|第8个男人 - 论坛为只读模式,仅供查阅

GMT+8, 2019-7-18 15:44 , Processed in 0.029740 second(s), 8 queries .

Design by pvo.cn

© 2011 Pvo Inc.

回顶部