{"id":5376,"date":"2022-06-04T00:01:37","date_gmt":"2022-06-04T07:01:37","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=5376"},"modified":"2022-06-11T07:09:48","modified_gmt":"2022-06-11T14:09:48","slug":"multiple-thread-mania","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=5376","title":{"rendered":"Multiple Thread Mania"},"content":{"rendered":"<p>In <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5365\">last week&#8217;s Lesson<\/a>, a program spawned a single thread. This thread runs at the same time as the main program, interrupting text input (if you let it). Such fun! But a multithreaded program isn&#8217;t limited to running just two threads. Your code can spawn multiple threads, each running simultaneously.<br \/>\n<!--more--><br \/>\nThe following code is based on the example from last week&#8217;s Lesson. But unlike that example, this code calls the <em>thread_funct()<\/em> function twice. I&#8217;ve modified the function so that it accepts an argument, which sets the character output.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2022_06_04-Lesson-a.c\" rel=\"noopener\" target=\"_blank\">2022_06_04-Lesson-a.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;unistd.h&gt;\r\n#include &lt;pthread.h&gt;\r\n\r\nvoid *thread_funct(void *a)\r\n{\r\n    const int loop=8;\r\n    int x;\r\n\r\n    for( x=0; x&lt;loop; x++ )\r\n    {\r\n        printf(\"%s\\n\",(char *)a);\r\n        sleep(1);\r\n    }\r\n\r\n    return(NULL);\r\n}\r\n\r\nint main()\r\n{\r\n    char buffer[BUFSIZ];\r\n    int r;\r\n    pthread_t thd1,thd2;\r\n\r\n    <span class=\"comments\">\/* spawn the thread 1 *\/<\/span>\r\n    r = pthread_create( &amp;thd1, NULL, thread_funct, \"*\");\r\n    if( r!=0 )\r\n    {\r\n        perror(\"Thread\");\r\n        exit(1);\r\n    }\r\n    \r\n    <span class=\"comments\">\/* spawn the thread 2 *\/<\/span>\r\n    r = pthread_create( &amp;thd2, NULL, thread_funct, \"#\");\r\n    if( r!=0 )\r\n    {\r\n        perror(\"Thread\");\r\n        exit(1);\r\n    }\r\n    \r\n    <span class=\"comments\">\/* prompt for your name *\/<\/span>\r\n    printf(\"What is your name? \");\r\n    fgets(buffer,BUFSIZ,stdin);\r\n    printf(\"Hello, %s\",buffer);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>Line 27 spawns the first thread, calling the <em>thread_funct()<\/em> function with <code>\"*\"<\/code> as its argument.<\/p>\n<p>Line 35 spawns the second thread, with <code>\"#\"<\/code> as the thread function&#8217;s argument.<\/p>\n<p>The result is that two characters appear as you attempt to type your name:<\/p>\n<p><code>What is your name? #<br \/>\n*<br \/>\n#<br \/>\n*<br \/>\nDa#<br \/>\n*<br \/>\nn #<br \/>\n*<br \/>\nGook#<br \/>\n*<br \/>\nin#<br \/>\n*<\/p>\n<p>Hello, Dan Gookin<\/code><\/p>\n<p>Both threads continue to run until they quit or you finish typing your name and the program quits.<\/p>\n<p>A thread need not run simultaneously, however, You can also direct the code to wait for a thread to finish. To handle this job, use the <em>thread_join()<\/em> function. Here&#8217;s its format:<\/p>\n<p><code>int pthread_join(pthread_t thread, void **value_ptr);<\/code><\/p>\n<p>The first argument is a <em>pthread_t<\/em> value representing a running thread. The second argument represents a return value received from the function, <code>NULL<\/code> to ignore the value or when nothing is returned.<\/p>\n<p>As with the <em>pthread_create()<\/em> function, zero is returned upon success. The global <em>errno<\/em> value is set upon failure. (Don&#8217;t rely on -1 as an error return value.)<\/p>\n<p>The following code runs two threads, one that&#8217;s spawned from the <em>thread_funct()<\/em> and the <em>main()<\/em> function. When the <em>pthread_join()<\/em> function is called at Line 35, the <em>main()<\/em> function suspends execution until the <em>thread_funct()<\/em> thread runs its course.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2022_06_04-Lesson-b.c\" rel=\"noopener\" target=\"_blank\">2022_06_04-Lesson-b.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;unistd.h&gt;\r\n#include &lt;pthread.h&gt;\r\n\r\nvoid *thread_funct(void *a)\r\n{\r\n    const int loop=8;\r\n    int x;\r\n\r\n    for( x=0; x&lt;loop; x++ )\r\n    {\r\n        printf(\"*\\n\");\r\n        sleep(1);\r\n    }\r\n\r\n    return(NULL);\r\n}\r\n\r\nint main()\r\n{\r\n    char buffer[BUFSIZ];\r\n    int r;\r\n    pthread_t thd;\r\n\r\n    <span class=\"comments\">\/* spawn the new thread *\/<\/span>\r\n    r = pthread_create( &amp;thd, NULL, thread_funct, NULL);\r\n    if( r!=0 )\r\n    {\r\n        perror(\"Thread\");\r\n        exit(1);\r\n    }\r\n    \r\n    <span class=\"comments\">\/* wait for the thread *\/<\/span>\r\n    r = pthread_join( thd, NULL );\r\n    if( r!=0 )\r\n    {\r\n        perror(\"Thread join\");\r\n        exit(1);\r\n    }\r\n\r\n    <span class=\"comments\">\/* prompt for your name *\/<\/span>\r\n    printf(\"What is your name? \");\r\n    fgets(buffer,BUFSIZ,stdin);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>Because the <em>pthread_join()<\/em> function is called right away, the spawned thread runs to completion. After the thread is done, the program then prompts for the user&#8217;s name:<\/p>\n<p><code>*<br \/>\n*<br \/>\n*<br \/>\n*<br \/>\n*<br \/>\n*<br \/>\n*<br \/>\n*<br \/>\nWhat is your name? Dan Gookin<br \/>\nHello, Dan Gookin<\/code><\/p>\n<p>Of course, the program runs the same as if the <em>thread_funct()<\/em> was just called and not spawned as a second thread. Still, this technique is how you can cause one thread to wait for another to finish its run.<\/p>\n<p>The <em>pthread_join()<\/em> function can also be used to capture a return value from a thread. This operation can be a bit tricky! I cover it in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5393\">next week&#8217;s Lesson<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Your program can spawn multiple threads, almost as many as a 600 thread count bedsheet &#8211; but not that crazy. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5376\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-5376","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5376","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5376"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5376\/revisions"}],"predecessor-version":[{"id":5415,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5376\/revisions\/5415"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5376"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5376"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5376"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}