{"id":4560,"date":"2015-12-23T16:46:13","date_gmt":"2015-12-23T16:46:13","guid":{"rendered":"http:\/\/anthroponaute.fr\/blog-informatique\/?p=4560"},"modified":"2020-02-07T11:02:19","modified_gmt":"2020-02-07T11:02:19","slug":"les-processus-legers-threads","status":"publish","type":"post","link":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/?p=4560","title":{"rendered":"Les processus l\u00e9gers (threads) avec std::thread (C++11)"},"content":{"rendered":"<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone\" src=\"https:\/\/upload.wikimedia.org\/wikipedia\/commons\/thumb\/a\/a5\/Multithreaded_process.svg\/220px-Multithreaded_process.svg.png\" alt=\"\" width=\"220\" height=\"208\" \/><\/p>\n<p><strong>Intro :<\/strong><\/p>\n<p>Les threads sont utilis\u00e9s dans ce qu&rsquo;on nomme\u00a0<strong>\u00a0\u00ab la programmation<\/strong> <strong>concurrente<\/strong> <strong>\u00bb<\/strong>, qui consiste en l&rsquo;ex\u00e9cution des <em>processus l\u00e9gers<\/em>. Cela repr\u00e9sente une s\u00e9quence d\u2019ex\u00e9cution du code d&rsquo;un programme au sein d&rsquo;un processus. Quelque part, les threads sont des processus l\u00e9gers qui sont ex\u00e9cut\u00e9s <em><strong>\u00ab\u00a0\u00e0 l&rsquo;int\u00e9rieur\u00a0\u00bb<\/strong><\/em> d&rsquo;un processus.<\/p>\n<p>Les threads d&rsquo;un m\u00eame processus partagent <strong>la m\u00eame m\u00e9moire<\/strong> et <strong>leurs variables<\/strong>. La <strong>pile<\/strong> de chaque thread <strong>est cependant unique<\/strong> pour chacun d&rsquo;entre-eux.<\/p>\n<p>Un processus habituel poss\u00e8de un<strong> seul thread<\/strong> et ce dernier correspond tout simplement au processus lui-m\u00eame.<\/p>\n<p>Soit c&rsquo;est le <strong>noyau du syst\u00e8me d&rsquo;exploitation<\/strong> qui s&rsquo;occupe des threads, soit ils sont g\u00e9r\u00e9s dans <strong>l&rsquo;espace utilisateur<\/strong> \u00e0 travers un gestionnaire sp\u00e9cial !<\/p>\n<p><strong>Pr\u00e9requis :<\/strong><\/p>\n<p>&#8211; Savoir lire du <em>C++<\/em><\/p>\n<p><strong>Explications :<\/strong><\/p>\n<p>Exemple d&rsquo;utilisation d&rsquo;un <strong>std::thread<\/strong> :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &lt;iostream&gt;\r\n#include &lt;thread&gt;\r\n\r\nvoid f()\r\n{\r\n\u00a0\u00a0 \u00a0std::cout &lt;&lt; &quot;Un thread C++11&quot; &lt;&lt; std::endl;\r\n}\r\n\r\nint main()\r\n{\r\n\u00a0\u00a0 \u00a0std::thread t(f);\r\n\r\n\u00a0\u00a0 \u00a0t.join();\r\n\r\n\u00a0\u00a0 \u00a0return 0;\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>La m\u00e9thode <strong>.join()<\/strong> permet d&rsquo;assurer que le thread se termine avant de quitter le programme ou la port\u00e9e du code. Cet appel est <strong><em>bloquant<\/em> <\/strong>!<\/p>\n<p>Un thread est dans l&rsquo;\u00e9tat <strong>\u00ab\u00a0joignable\u00a0\u00bb<\/strong> s&rsquo;il est est cr\u00e9\u00e9 avec une t\u00e2che \u00e0 r\u00e9aliser.<\/p>\n<p>Le type <strong>std::thread (C++11)<\/strong> a une m\u00e9thode<strong><em> get_id()<\/em><\/strong> afin d&rsquo;obtenir l&rsquo;id du thread en question.<\/p>\n<p>Il peut exister un<strong> probl\u00e8me de synchronisation<\/strong> entre deux threads ! On doit <strong>prot\u00e9ger l&rsquo;acc\u00e8s<\/strong> \u00e0 certaines ressources si deux threads distincts sont en train d&rsquo;y <strong>acc\u00e9der en \u00e9criture<\/strong>.<\/p>\n<p>Un thread peut \u00eatre aussi <strong>d\u00e9tach\u00e9<\/strong> :<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &lt;iostream&gt;\r\n#include &lt;thread&gt;\r\n\r\nvoid f()\r\n{\r\n\u00a0\u00a0\u00a0 std::cout&lt;&lt; &quot;Un thread C++11&quot; &lt;&lt; std::endl;\r\n}\r\n\r\nint main()\r\n{\r\n\u00a0\u00a0\u00a0 std::thread t(f);\r\n    t.join();\r\n\u00a0\u00a0\u00a0 t.detach();\r\n\r\n\u00a0\u00a0\u00a0 return 0;\r\n}\r\n<\/pre>\n<hr \/>\n<p><em><strong>Qu&rsquo;est-ce qu&rsquo;un s\u00e9maphore ?<\/strong><\/em><\/p>\n<p>Il permet de synchroniser l&rsquo;acc\u00e8s \u00e0 une<strong> ressource partag\u00e9e<\/strong>. Cette ressource peut aussi bien \u00eatre un bout de code !<\/p>\n<p>Les threads acc\u00e8dent aux ressources par le biais de ce <strong>s\u00e9maphore<\/strong>.<\/p>\n<p>Pendant que le thread ex\u00e9cute cette ressource partag\u00e9e <strong>aucun autre thread ne peut y acc\u00e9der<\/strong>. D\u00e8s qu&rsquo;il a termin\u00e9 son travail, il lib\u00e8re le s\u00e9maphore (qui est nomm\u00e9 aussi <strong>\u00ab\u00a0moniteur\u00a0\u00bb<\/strong>).<\/p>\n<hr \/>\n<p><em><strong>Qu&rsquo;est-ce qu&rsquo;un mutex ?<\/strong><\/em><\/p>\n<p>Le mot <strong>\u00ab\u00a0mutex\u00a0\u00bb<\/strong> provient de l\u2019abr\u00e9viation <em><strong>\u00ab\u00a0Mutual Exclusion\u00a0\u00bb. <\/strong><\/em>Il assure que les donn\u00e9es partag\u00e9es sont <em>\u00ab\u00a0mutuellement exclusives\u00a0\u00bb. <\/em>Il s&rsquo;agit juste d&rsquo;une variable qui peut \u00eatre soit dans l&rsquo;\u00e9tat \u00ab\u00a0<strong><em>verrouill\u00e9<\/em><\/strong>\u00a0\u00bb ou soit dans l&rsquo;\u00e9tat \u00ab\u00a0<strong><em>d\u00e9verrouill\u00e9<\/em><\/strong>\u00a0\u00bb !<\/p>\n<p>Pour verrouiller un <em><strong>mutex<\/strong> <\/em>on utilise la m\u00e9thode <strong>lock()<\/strong>.<\/p>\n<p>D\u00e8s qu&rsquo;un thread a fini de travailler avec une donn\u00e9e \/ ressource partag\u00e9e il doit lib\u00e9rer le <em><strong>mutex<\/strong> <\/em>! Il faut utiliser la m\u00e9thode <strong>unlock()<\/strong>.<\/p>\n<p>On peut d\u00e9clarer le <em><strong>mutex<\/strong> <\/em>en m\u00eame temps que la variable \u00e0 prot\u00e9ger !<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nstruct Data\r\n{\r\n\u00a0\u00a0\u00a0 int var;\r\n\u00a0\u00a0\u00a0 std::mutex mutex;\r\n};\r\n<\/pre>\n<div data-canvas-width=\"602.9829328127998\"><\/div>\n<p>&nbsp;<\/p>\n<p><em><strong>Qu&rsquo;est-ce qu&rsquo;une condition ?<\/strong><\/em><\/p>\n<p>Une <em><strong>condition<\/strong> <\/em>est n\u00e9cessaire d&rsquo;\u00eatre utilis\u00e9e si l&rsquo;on veut qu&rsquo;un thread patiente \u00e0 l\u2019\u00e9v\u00e9nement d&rsquo;un autre thread.<\/p>\n<p>Lorsqu&rsquo;un thread est en attente d&rsquo;une condition, il reste bloqu\u00e9 jusqu&rsquo;\u00e0 ce que la condition soit r\u00e9aliser par un autre thread.<\/p>\n<p><strong>R\u00e9sum\u00e9 : <\/strong><\/p>\n<p>Nous avons pr\u00e9senter l&rsquo;utilisation des <strong>thread (processus l\u00e9ger)<\/strong> afin de r\u00e9partir l\u2019ex\u00e9cution des bouts de code d&rsquo;un jeu-vid\u00e9o.<\/p>\n<p>En effet, les programmes utilisant des threads sur des architectures de type <strong><em>multi-processeurs<\/em><\/strong> sont plus rapides que les programmes plus classiques !<\/p>\n<p><strong>R\u00e9f\u00e9rences :<\/strong><\/p>\n<p>&#8211; http:\/\/www.iro.umontreal.ca\/~dift1169\/cours\/ift1169\/communs\/Cours\/2P\/C12_1169_2P.pdf<\/p>\n<p>&#8211; https:\/\/fr.wikipedia.org\/wiki\/Thread_(informatique)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Intro : Les threads sont utilis\u00e9s dans ce qu&rsquo;on nomme\u00a0\u00a0\u00ab la programmation concurrente \u00bb, qui consiste en l&rsquo;ex\u00e9cution des processus l\u00e9gers. Cela repr\u00e9sente une s\u00e9quence d\u2019ex\u00e9cution du code d&rsquo;un programme au sein d&rsquo;un processus. Quelque part, les threads sont des processus l\u00e9gers qui sont ex\u00e9cut\u00e9s \u00ab\u00a0\u00e0 l&rsquo;int\u00e9rieur\u00a0\u00bb d&rsquo;un processus. Les threads d&rsquo;un m\u00eame processus partagent [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[],"_links":{"self":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/4560"}],"collection":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4560"}],"version-history":[{"count":83,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/4560\/revisions"}],"predecessor-version":[{"id":5326,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=\/wp\/v2\/posts\/4560\/revisions\/5326"}],"wp:attachment":[{"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4560"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4560"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.la-porte-des-nebuleuses.net\/blog-informatique\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4560"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}