{"id":33943,"date":"2005-10-03T10:00:08","date_gmt":"2005-10-03T10:00:08","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/10\/03\/consequences-of-the-scheduling-algorithm-low-priority-threads-can-run-even-when-higher-priority-threads-are-running\/"},"modified":"2005-10-03T10:00:08","modified_gmt":"2005-10-03T10:00:08","slug":"consequences-of-the-scheduling-algorithm-low-priority-threads-can-run-even-when-higher-priority-threads-are-running","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20051003-08\/?p=33943","title":{"rendered":"Consequences of the scheduling algorithm: Low priority threads can run even when higher priority threads are running"},"content":{"rendered":"<p><P>\nJust because you have a thread running at a higher priority\nlevel doesn&#8217;t mean that no threads of lower priority will ever run.\n<\/P>\n<P>\nOccasionally, I see people write multi-threaded code and put\none thread&#8217;s priority higher than the other, assuming that\nthis will prevent the lower-priority thread from interfering\nwith the operation of the higher-priority thread\nso that they don&#8217;t need to do any explicit synchronization.\n<\/P>\n<PRE>\nBOOL g_fReady;\nint g_iResult;\n\/\/ high priority thread\nSetResult(int iResult)\n{\n g_fReady = TRUE;\n g_iResult = iResult;\n}<\/p>\n<p>\/\/ low priority thread\nif (g_fReady)\n{\n UseResult(g_iResult);\n}\n<\/PRE>\n<P>\nLet&#8217;s ignore the cache coherency elephant in the room.\nIf there were a guarantee that the low priority thread will never\never run while the high priority thread is running, this code looks\nokay.  Even if the high priority thread interrupts and sets\nthe result after the low priority thread has checked the ready flag,\nall that happens is that the low priority thread misses out on the result.\n(This is hardly a new issue, since\n<A HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2004\/09\/03\/225238.aspx\">\nthe principle of relativity of simultaneity<\/A>\nsays that this was a possibility anyway.)\n<\/P>\n<P>\nHowever, there is no guarantee that the low priority thread can&#8217;t\ninterfere with the high priority thread.\n<\/P>\n<P>\nThe scheduler&#8217;s rule is to look for the thread with the highest\npriority that is &#8220;runnable&#8221;, i.e., ready to run,\nand assign it to a CPU for execution.\nTo be ready to run, a thread cannot be blocked on anything,\nand it can&#8217;t already be running on another CPU.\nIf there is a tie among runnable threads for the highest priority,\nthen the scheduler shares the CPU among them roughly equally.\n<\/P>\n<P>\nYou might think that, given these rules,\nas long as there is a high priority thread that is runnable,\nthen no lower-priority thread will run.\nBut that&#8217;s not true.\n<\/P>\n<P>\nConsider the case of a multi-processor system\n(and with the advent of hyperthreading, this is\nbecoming more and more prevalent),\nwhere there are two runnable threads, one with higher priority\nthan the other.\nThe scheduler will first assign the high-priority thread\nto one of the processors.\nBut it still has a spare CPU to burn,\nso the low-priority thread will be assigned to the second CPU.\nYou now have a lower priority thread running simultaneously\nas a higher priority thread.\n<\/P>\n<P>\nOf course, another way a lower priority thread can run even\nthough there are higher priority threads in the system is\nsimply that all the higher priority threads are blocked.\nIn addition to the cases you might expect, namely\nwaiting on a synchronization object such as a semaphore\nor a critical section,\na thread can also block for I\/O or for paging.\nPaging is the wildcard here, since you don&#8217;t have any\ncontrol over when the system might decide to page out\nthe memory you were using due to memory pressure\nelsewhere in the system.\n<\/P>\n<P>\nThe moral of the story is that thread priorities are not\na substitute for proper synchronization.\n<\/P>\n<P>\nNext time, a reversal of this fallacy.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Just because you have a thread running at a higher priority level doesn&#8217;t mean that no threads of lower priority will ever run. Occasionally, I see people write multi-threaded code and put one thread&#8217;s priority higher than the other, assuming that this will prevent the lower-priority thread from interfering with the operation of the higher-priority [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-33943","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Just because you have a thread running at a higher priority level doesn&#8217;t mean that no threads of lower priority will ever run. Occasionally, I see people write multi-threaded code and put one thread&#8217;s priority higher than the other, assuming that this will prevent the lower-priority thread from interfering with the operation of the higher-priority [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/33943","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=33943"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/33943\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=33943"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=33943"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=33943"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}