### 線程例子

計算3個線程總共循環了多少次，main_counter 是直接計算總的循環次數，counter[i] 是計算第 i 號線程循環的次數。sum 是3個線程各自循環次數的總和。所以，理論上main_counter 和 sum 值應該是相等的，因為都是在計算總循環次數。

`<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<stdio.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<stdlib.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<sys/types.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<unistd.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<ctype.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<pthread.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#define MAX_THREAD  3  <span class="hljs-comment" style="box-sizing: border-box;">//線程個數</span></span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span>   main_counter,counter[MAX_THREAD]={<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>};<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>* thread_worker(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>*  arg){<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//將指針先強轉為int* 再賦值 </span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>  thread_num = *(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>*)arg;<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//    printf("thread_id:%lu   counter[%d]\n",pthread_self(),thread_num);</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(;;)    {        counter[thread_num]++;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//本線程的counter 加 1</span>        main_counter++;    }}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>* argv[]){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>                 i,rtn,ch;    pthread_t           pthread_id[MAX_THREAD] =  {<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>};  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//存放線程</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<MAX_THREAD;i++)    {<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//傳 &i </span>        pthread_create(&pthread_id[i],NULL,thread_worker,&i);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">do</span>    {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span>   sum = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<MAX_THREAD;i++)        {            sum += counter[i];            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"No.%d: %llu\n"</span>,i,counter[i]);        }        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%llu/%llu\n"</span>,main_counter,sum);    }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>((ch = getchar())!=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'q'</span>);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li></ul>`

#### 問題1：傳參很詭異

正像上面代碼中那樣，我們在創建線程的時候習慣於傳指針或取地址進去，即 &i ：

`<code class="hljs css has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">pthread_create</span>(&<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">pthread_id</span><span class="hljs-attr_selector" style="color: rgb(0, 136, 0); box-sizing: border-box;">[i]</span>,<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">NULL</span>,<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">thread_worker</span>,&<span class="hljs-tag" style="color: rgb(0, 0, 0); box-sizing: border-box;">i</span>);</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>`

1、 值傳遞

`<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>void* thread_worker(void*  arg){    int  thread_num = (int)arg;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>}int main(int argc,char* argv[]){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<MAX_THREAD;i++)    {         pthread_create(&pthread_id[i],<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span>,thread_worker,(void*)i);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li></ul>`

2、 借用數組傳參

`<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">//關鍵代碼void* thread_worker(void*  arg){    //先將void* 轉為 int* 再賦值    int  thread_num = *(int*)arg;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>}int main(int argc,char* argv[]){    int                 i,rtn,ch;    pthread_t           pthread_id[MAX_THREAD] =  {<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>};  //存放線程    //保存參數的數組    int                 param[<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>];    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<MAX_THREAD;i++)    {         param[i] = i;        pthread_create(&pthread_id[i],<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span>,thread_worker,param+i);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li></ul>`

3、動態申請臨時內存

`<code class="hljs r has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>void* thread_worker(void*  arg){    //先將void* 轉為 int* 再賦值    int  thread_num = *(int*)arg;    //釋放內存    free((int*)arg);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>}int main(int argc,char* argv[]){    int                 i,rtn,ch;    pthread_t           pthread_id[MAX_THREAD] =  {<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>};  //存放線程    int                 *param;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<MAX_THREAD;i++)    {         //申請內存臨時保存參數        param = (int*)malloc(sizeof(int));        *param = i;        pthread_create(&pthread_id[i],<span class="hljs-literal" style="color: rgb(0, 102, 102); box-sizing: border-box;">NULL</span>,thread_worker,param);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">...</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li></ul>`

#### 問題2： main_counter < sum

解決了問題1，我們發現還有問題，main_counter 居然不等於 sum 的值，與理論不符。這主要是由於 main_counter++ 語句並不是原子操作。

通俗的將，就是線程執行某個操作的時候不能被其他線程打斷或破壞。好比說，你去食堂吃飯，剛刷了卡，結果給你的菜卻被另一個剛來的同學給端走了。

`<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//初始化鎖</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> pthread_mutex_t    mutex = PTHREAD_MUTEX_INITIALIZER;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span>   main_counter,counter[MAX_THREAD]={<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>};<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>* thread_worker(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>*  arg){    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//先將void* 轉為 int* 再賦值</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>  thread_num = *(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>*)arg;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//釋放內存</span>    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">free</span>((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>*)arg);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(;;)    {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//加鎖</span>        pthread_mutex_lock(&mutex);        counter[thread_num]++;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//本線程的counter 加 1</span>        main_counter++;        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//解鎖</span>        pthread_mutex_unlock(&mutex);    }}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>* argv[]){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>                 i,rtn,ch;    pthread_t           pthread_id[MAX_THREAD] =  {<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>};  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//存放線程</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>                 *param;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<MAX_THREAD;i++)    {         <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//申請內存臨時保存參數</span>        param = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>*)<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">malloc</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>));        *param = i;        pthread_create(&pthread_id[i],NULL,thread_worker,param);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">do</span>    {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span>   sum = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<MAX_THREAD;i++)        {            sum += counter[i];            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"No.%d: %llu\n"</span>,i,counter[i]);        }        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%llu/%llu\n"</span>,main_counter,sum);    }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>((ch = getchar())!=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'q'</span>);    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//銷毀鎖資源</span>    pthread_mutex_destroy(&mutex);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li></ul>`

#### 問題3：main_counter 為毛比 sum 大了？

其實這是主線程輸出的問題，問題主要出在以下這段代碼：

（1）如果在主線程剛執行完求和操作還未輸出時，時間片用完了，CPU被子線程搶占，執行了main_counter++，但sum 不會再同步增加了，所以最后輸出時，main_counter > sum 。
（2）如果是多核CPU，在主線程完成求和操作到輸出結果這一段時間內很可能有子線程在並行執行main_counter++,同樣sum 卻不會增加，導致輸出時，main_counter > sum 。

在單核系統上，運行出現異常是原因（1）導致，因為單核上CPU調度線程是用的時間片輪轉。大概因為57～62 行這幾條語句執行時間太短了，一個時間片內可以執行完，幾乎不會在中途被打斷。

我們可以在62行前加 sleep 睡眠，這時，隱患就暴露出來了。

解決問題的關鍵就是 a、要讓 main_counter++ 和 counter[i]++ 是保持同步更新的， 這兩條語句中間不能被打斷; b、求和操作完成后，不能再讓 main_counter 增加。

`<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<stdio.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<stdlib.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<sys/types.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<unistd.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<ctype.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#include<pthread.h></span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">#define MAX_THREAD  3  <span class="hljs-comment" style="box-sizing: border-box;">//線程個數</span></span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//初始化鎖</span><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">static</span> pthread_mutex_t    mutex = PTHREAD_MUTEX_INITIALIZER;<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span>   main_counter,counter[MAX_THREAD]={<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>};<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>* thread_worker(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span>*  arg){    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//先將void* 轉為 int* 再賦值</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>  thread_num = *(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>*)arg;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//釋放內存</span>    <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">free</span>((<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>*)arg);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(;;)    {        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//加鎖</span>        pthread_mutex_lock(&mutex);        counter[thread_num]++;    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//本線程的counter 加 1</span>        main_counter++;    }}<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> main(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> argc,<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">char</span>* argv[]){    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>                 i,rtn,ch;    pthread_t           pthread_id[MAX_THREAD] =  {<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>};  <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//存放線程</span>    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>                 *param;    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<MAX_THREAD;i++)    {         <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//申請內存臨時保存參數</span>        param = (<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>*)<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">malloc</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">sizeof</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span>));        *param = i;        pthread_create(&pthread_id[i],NULL,thread_worker,param);    }    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">do</span>    {        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">unsigned</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span>   sum = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span>(i=<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;i<MAX_THREAD;i++)        {            sum += counter[i];            <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"No.%d: %llu\n"</span>,i,counter[i]);        }        <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">printf</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"%llu/%llu\n"</span>,main_counter,sum);        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//解鎖</span>        pthread_mutex_unlock(&mutex);    }<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>((ch = getchar())!=<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">'q'</span>);    <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//銷毀鎖資源</span>    pthread_mutex_destroy(&mutex);    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>;}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li></ul>`

解決了所有問題后，線程運行的效率遠遠的變慢了，這是因為鎖的存在導致一個線程在運行時，其他線程幾乎是在阻塞的。但是大可不必在意這個，因為這個程序只是用來幫助更好的理解線程資源共享、線程並行、線程搶占和線程調度的，實際應用中，肯定不會把一個求和操作搞的這么錯綜復雜的。