{"id":33233,"date":"2005-11-23T10:00:14","date_gmt":"2005-11-23T10:00:14","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2005\/11\/23\/semaphores-dont-have-owners\/"},"modified":"2005-11-23T10:00:14","modified_gmt":"2005-11-23T10:00:14","slug":"semaphores-dont-have-owners","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20051123-14\/?p=33233","title":{"rendered":"Semaphores don&#8217;t have owners"},"content":{"rendered":"<p><P>\nUnlike mutexes and critical sections,\nsemaphores don&#8217;t have owners.\nThey merely have counts.\n<\/P>\n<P>\n<A HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/dllproc\/base\/releasesemaphore.asp\">\nThe <CODE>ReleaseSemaphore<\/CODE> function<\/A>\nincreases the count associated with a semaphore\nby the specified amount.\n(This increase might release waiting threads.)\nBut the thread releasing the semaphore need not be the same\none that claimed it originally.\nThis is different from mutexes and critical sections,\nwhich require that the claiming thread also be the releasing one.\n<\/P>\n<P>\n<A HREF=\"http:\/\/groups-beta.google.com\/group\/microsoft.public.win32.programmer.kernel\/msg\/1719b379039097fc\">\nSome people use semaphores in a mutex-like manner<\/A>:\nThey create a semaphore with initial count&nbsp;1 and\nuse it like this:\n<\/P>\n<PRE>\nWaitForSingleObject(hSemaphore, INFINITE);\n&#8230; do stuff ..\nReleaseSemaphore(hSemaphore, 1, NULL);\n<\/PRE>\n<P>\nIf the thread exits (or crashes) before it manages to release the semaphore,\nthe semaphore counter is not automatically restored.\nCompare mutexes, where the mutex is released if the owner thread\nterminates while holding it.\nFor this pattern of usage, a mutex is therefore preferable.\n<\/P>\n<P>\nA semaphore is useful if the conceptual ownership of a resource\ncan cross threads.\n<\/P>\n<PRE>\nWaitForSingleObject(hSemaphore, INFINITE);\n&#8230; do some work ..\n&#8230; continue on a background thread &#8230;\nHANDLE hThread = CreateThread(NULL, 0, KeepWorking, &#8230;);\nif (!hThread) {\n  &#8230; abandon work &#8230;\n  ReleaseSemaphore(hSemaphore, 1, NULL); \/\/ release resources\n}<\/p>\n<p>DWORD CALLBACK KeepWorking(void* lpParameter)\n{\n  &#8230; finish working &#8230;\n  ReleaseSemaphore(hSemaphore, 1, NULL);\n  return 0;\n}\n<\/PRE>\n<P>\nThis trick doesn&#8217;t work with a mutex or critical section because\nmutexes and critical sections have owners, and only the owner can\nrelease the mutex or critical section.\n<\/P>\n<P>\nNote that if the <CODE>KeepWorking<\/CODE> function exits and\nforgets to release the semaphore, then the counter is not\nautomatically restored.  The operating system doesn&#8217;t know that\nthe semaphore &#8220;belongs to&#8221; that work item.\n<\/P>\n<P>\nAnother common usage pattern for a semaphore is the opposite of\nthe resource-protection pattern: It&#8217;s the resource-generation\npattern.  In this model the semaphore count normally is zero,\nbut is incremented when there is work to be done.\n<\/P>\n<PRE>\n&#8230; produce some work and add it to a work list &#8230;\nReleaseSemaphore(hSemaphore, 1, NULL);<\/p>\n<p>\/\/ There can be more than one worker thread.\n\/\/ Each time a work item is signalled, one thread will\n\/\/ be chosen to process it.\nDWORD CALLBACK ProcessWork(void* lpParameter)\n{\n  for (;;) {\n    \/\/ wait for work to show up\n    WaitForSingleObject(hSemaphore, INFINITE);\n    &#8230; retrieve a work item from the work list &#8230;\n    &#8230; perform the work &#8230;\n  }\n  \/\/ NOTREACHED\n}\n<\/PRE>\n<P>\nNotice that in this case, there is not even a conceptual\n&#8220;owner&#8221; of the semaphore, unless you count the work item itself\n(sitting on a work list data structure somewhere)\nas the owner.  If the <CODE>ProcessWork<\/CODE> thread exits,\nyou do <STRONG>not<\/STRONG> want the semaphore to be released\nautomatically; that would mess up the accounting.\nA semaphore is an appropriate object in this case.\n<\/P>\n<P>\n(A higher performance version of the producer\/consumer semaphore\nis the\n<A HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/fileio\/base\/i_o_completion_ports.asp\">\nI\/O completion port<\/A>.)\n<\/P>\n<P>\nArmed with this information, see if you can answer\n<A HREF=\"http:\/\/groups.google.com\/groups?selm=5ca11246.0110092312.1a40ca2e@posting.google.com\">\nthis person&#8217;s question<\/A>.\n<\/P>\n<P>\n[Raymond is currently away; this message was pre-recorded.]\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Unlike mutexes and critical sections, semaphores don&#8217;t have owners. They merely have counts. The ReleaseSemaphore function increases the count associated with a semaphore by the specified amount. (This increase might release waiting threads.) But the thread releasing the semaphore need not be the same one that claimed it originally. This is different from mutexes and [&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-33233","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Unlike mutexes and critical sections, semaphores don&#8217;t have owners. They merely have counts. The ReleaseSemaphore function increases the count associated with a semaphore by the specified amount. (This increase might release waiting threads.) But the thread releasing the semaphore need not be the same one that claimed it originally. This is different from mutexes and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/33233","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=33233"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/33233\/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=33233"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=33233"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=33233"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}