非常感谢你的文章!如果没有这篇文章,可能我还得看很久才能理出头绪。非常感谢!
有几处我看到的和文章中说的不一样。写下来,可做讨论:
1. workQueues的偶数位置(外部提交的任务)是不配线程的。它们是shared的,就是总是被偷去执行的。
2. 外部提交的任务不是随机找位置的,是确定的。每个线程维护一个数(probe),只要这个数不变,每次提交任务都到同一个任务队列;如果那个队列太忙了,就会提交失败,这时候就把数变一下,重新提交,直到成功,将来的任务也都会提交到这个新地方。
3. 子任务fork()出来的新任务永远放在执行它的worker所拥有的队列里。如果它不被偷,就是原来的队列;如果被偷了,就是偷窃者的队列。
4. 新的任务队列及其对应的worker线程的产生是被动的方式:每当有新任务来的时候,都会调用signalWork()方法。这个方法检查当前的线程是否够用,如果不够用,就释放一个闲置线程(idle worker);如果没有闲置线程,就创建一个新线程。新线程创建后,配给它一个新建的任务队列,然后在workQueues里找一个合适的位置(奇数位置)把任务队列放进去,这个位置不是随机的,而是算出来的:从上一次新建队列的位置向后移动一个固定的偏移量。
5. 补偿线程的意思是:一个线程执行join()的时候知道自己注定要去block了,因此唤醒或者新建一个线程补偿自己block之后的算力损失。