日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

Step by Step:Linux C多線(xiàn)程編程入門(mén)(基本API

系統(tǒng) 2358 0

Step by Step:Linux C多線(xiàn)程編程入門(mén)(基本API及多線(xiàn)程的同步與互斥)

介紹:什么是線(xiàn)程,線(xiàn)程的優(yōu)點(diǎn)是什么

線(xiàn)程在Unix系統(tǒng)下,通常被稱(chēng)為輕量級(jí)的進(jìn)程,線(xiàn)程雖然不是進(jìn)程,但卻可以看作是Unix進(jìn)程的表親,同一進(jìn)程中的多條線(xiàn)程將 共享該進(jìn)程中的全部系統(tǒng)資源,如虛擬地址空間,文件描述符和信號(hào)處理等等 。但同一進(jìn)程中的多個(gè)線(xiàn)程 有各自的調(diào)用棧(call stack),自己的寄存器環(huán)境(register context),自己的線(xiàn)程本地存儲(chǔ)(thread-local storage) 。 一個(gè)進(jìn)程可以有很多線(xiàn)程,每條線(xiàn)程并行執(zhí)行不同的任務(wù)。

線(xiàn)程可以提高應(yīng)用程序在多核環(huán)境下處理諸如文件I/O或者socket I/O等會(huì)產(chǎn)生堵塞的情況的表現(xiàn)性能。在Unix系統(tǒng)中,一個(gè)進(jìn)程包含很多東西,包括可執(zhí)行程序以及一大堆的諸如文件描述符地址空間等資源。在很多情況下,完成相關(guān)任務(wù)的不同代碼間需要交換數(shù)據(jù)。如果采用多進(jìn)程的方式,那么通信就需要在用戶(hù)空間和內(nèi)核空間進(jìn)行頻繁的切換,開(kāi)銷(xiāo)很大。但是如果使用多線(xiàn)程的方式,因?yàn)榭梢允褂霉蚕淼娜肿兞浚跃€(xiàn)程間的通信(數(shù)據(jù)交換)變得非常高效。

Hello World(線(xiàn)程創(chuàng)建、結(jié)束、等待)

創(chuàng)建線(xiàn)程 pthread_create

線(xiàn)程創(chuàng)建函數(shù)包含四個(gè)變量,分別為: 1. 一個(gè)線(xiàn)程變量名,被創(chuàng)建線(xiàn)程的標(biāo)識(shí) 2. 線(xiàn)程的屬性指針,缺省為NULL即可 3. 被創(chuàng)建線(xiàn)程的程序代碼 4. 程序代碼的參數(shù) For example: - pthread_t thrd1; - pthread_attr_t? attr; - void thread_function(void? argument); - char *some_argument;

pthread_create(&thrd1, NULL, (void *)&thread_function, (void *) &some_argument);

結(jié)束線(xiàn)程 pthread_exit

線(xiàn)程結(jié)束調(diào)用實(shí)例: pthread_exit(void *retval); ?//retval用于存放線(xiàn)程結(jié)束的退出狀態(tài)

線(xiàn)程等待 pthread_join

pthread_create調(diào)用成功以后,新線(xiàn)程和老線(xiàn)程誰(shuí)先執(zhí)行,誰(shuí)后執(zhí)行用戶(hù)是不知道的,這一塊取決與操作系統(tǒng)對(duì)線(xiàn)程的調(diào)度,如果我們需要等待指定線(xiàn)程結(jié)束,需要使用pthread_join函數(shù),這個(gè)函數(shù)實(shí)際上類(lèi)似與多進(jìn)程編程中的waitpid。 舉個(gè)例子,以下假設(shè) A 線(xiàn)程調(diào)用 pthread_join 試圖去操作B線(xiàn)程,該函數(shù)將A線(xiàn)程阻塞,直到B線(xiàn)程退出,當(dāng)B線(xiàn)程退出以后,A線(xiàn)程會(huì)收集B線(xiàn)程的返回碼。 該函數(shù)包含兩個(gè)參數(shù):

  • pthread_t th //th是要等待結(jié)束的線(xiàn)程的標(biāo)識(shí)
  • void **thread_return //指針thread_return指向的位置存放的是終止線(xiàn)程的返回狀態(tài)。

調(diào)用實(shí)例: pthread_join(thrd1, NULL);

example1:

        
           1
        
        
          /*
        
        
          ************************************************************************


        
        
           2
        
        
              > File Name: thread_hello_world.c 


        
        
           3
        
        
              > Author: couldtt(fyby)


        
        
           4
        
        
              > Mail:  fuyunbiyi@gmail.com


        
        
           5
        
        
              > Created Time: 2013年12月14日 星期六 11時(shí)48分50秒


        
        
           6
        
        
           ***********************************************************************
        
        
          */
        
        
           7
        
        
           8
        
         #include <stdio.h>


        
           9
        
         #include <stdlib.h>


        
          10
        
         #include <pthread.h>


        
          11
        
        
          12
        
        
          void
        
         print_message_function (
        
          void
        
         *
        
          ptr);


        
        
          13
        
        
          14
        
        
          int
        
        
           main()


        
        
          15
        
        
          {


        
        
          16
        
        
          int
        
        
           tmp1, tmp2;


        
        
          17
        
        
          void
        
         *
        
          retval;


        
        
          18
        
        
              pthread_t thread1, thread2;


        
        
          19
        
        
          char
        
         *message1 = 
        
          "
        
        
          thread1
        
        
          "
        
        
          ;


        
        
          20
        
        
          char
        
         *message2 = 
        
          "
        
        
          thread2
        
        
          "
        
        
          ;


        
        
          21
        
        
          22
        
        
          int
        
        
           ret_thrd1, ret_thrd2;


        
        
          23
        
        
          24
        
             ret_thrd1 = pthread_create(&thread1, NULL, (
        
          void
        
         *)&print_message_function, (
        
          void
        
         *
        
          ) message1);


        
        
          25
        
             ret_thrd2 = pthread_create(&thread2, NULL, (
        
          void
        
         *)&print_message_function, (
        
          void
        
         *
        
          ) message2);


        
        
          26
        
        
          27
        
        
          //
        
        
           線(xiàn)程創(chuàng)建成功,返回0,失敗返回失敗號(hào)
        
        
          28
        
        
          if
        
         (ret_thrd1 != 
        
          0
        
        
          ) {


        
        
          29
        
                 printf(
        
          "
        
        
          線(xiàn)程1創(chuàng)建失敗\n
        
        
          "
        
        
          );


        
        
          30
        
             } 
        
          else
        
        
           {


        
        
          31
        
                 printf(
        
          "
        
        
          線(xiàn)程1創(chuàng)建成功\n
        
        
          "
        
        
          );


        
        
          32
        
        
              }


        
        
          33
        
        
          34
        
        
          if
        
         (ret_thrd2 != 
        
          0
        
        
          ) {


        
        
          35
        
                 printf(
        
          "
        
        
          線(xiàn)程2創(chuàng)建失敗\n
        
        
          "
        
        
          );


        
        
          36
        
             } 
        
          else
        
        
           {


        
        
          37
        
                 printf(
        
          "
        
        
          線(xiàn)程2創(chuàng)建成功\n
        
        
          "
        
        
          );


        
        
          38
        
        
              }


        
        
          39
        
        
          40
        
        
          //
        
        
          同樣,pthread_join的返回值成功為0
        
        
          41
        
             tmp1 = pthread_join(thread1, &
        
          retval);


        
        
          42
        
             printf(
        
          "
        
        
          thread1 return value(retval) is %d\n
        
        
          "
        
        , (
        
          int
        
        
          )retval);


        
        
          43
        
             printf(
        
          "
        
        
          thread1 return value(tmp) is %d\n
        
        
          "
        
        
          , tmp1);


        
        
          44
        
        
          if
        
         (tmp1 != 
        
          0
        
        
          ) {


        
        
          45
        
                 printf(
        
          "
        
        
          cannot join with thread1\n
        
        
          "
        
        
          );


        
        
          46
        
        
              }


        
        
          47
        
             printf(
        
          "
        
        
          thread1 end\n
        
        
          "
        
        
          );


        
        
          48
        
        
          49
        
             tmp2 = pthread_join(thread1, &
        
          retval);


        
        
          50
        
             printf(
        
          "
        
        
          thread2 return value(retval) is %d\n
        
        
          "
        
        , (
        
          int
        
        
          )retval);


        
        
          51
        
             printf(
        
          "
        
        
          thread2 return value(tmp) is %d\n
        
        
          "
        
        
          , tmp1);


        
        
          52
        
        
          if
        
         (tmp2 != 
        
          0
        
        
          ) {


        
        
          53
        
                 printf(
        
          "
        
        
          cannot join with thread2\n
        
        
          "
        
        
          );


        
        
          54
        
        
              }


        
        
          55
        
             printf(
        
          "
        
        
          thread2 end\n
        
        
          "
        
        
          );


        
        
          56
        
        
          57
        
        
          }


        
        
          58
        
        
          59
        
        
          void
        
         print_message_function( 
        
          void
        
         *
        
          ptr ) {


        
        
          60
        
        
          int
        
         i = 
        
          0
        
        
          ;


        
        
          61
        
        
          for
        
         (i; i<
        
          5
        
        ; i++
        
          ) {


        
        
          62
        
                 printf(
        
          "
        
        
          %s:%d\n
        
        
          "
        
        , (
        
          char
        
         *
        
          )ptr, i);


        
        
          63
        
        
              }


        
        
          64
        
         }
      

?

編譯

gcc thread_hello_world.c -otest -lpthread ?一定要加上 -lpthread ,要不然會(huì)報(bào)錯(cuò),因?yàn)樵创a里引用了pthread.h里的東西,所以在gcc進(jìn)行鏈接的時(shí)候,必須要找到這些庫(kù)的二進(jìn)制實(shí)現(xiàn)代碼。

運(yùn)行結(jié)果

?結(jié)果分析: 1.這段程序我運(yùn)行了兩次,可以看到,兩次的運(yùn)行結(jié)果是不一樣的,從而說(shuō)明, 新線(xiàn)程和老線(xiàn)程誰(shuí)先執(zhí)行,誰(shuí)后執(zhí)行用戶(hù)是不知道的,這一塊取決與操作系統(tǒng)對(duì)線(xiàn)程的調(diào)度 。 2.另外,我們看到,在thread2的join結(jié)果出現(xiàn)了錯(cuò)誤,打印出 cannot join with thread2 其實(shí)這個(gè)是個(gè)小錯(cuò)誤,因?yàn)?我pthread_join傳進(jìn)去的th是thread1,在上面的結(jié)果中,thread1早已經(jīng)結(jié)束了,所以我們?cè)俅蔚却齮hread1結(jié)束肯定會(huì)出現(xiàn)無(wú)法取到狀態(tài)的錯(cuò)誤的。 3.pthread_join(thread1, &retval)確實(shí)等待了thread1的結(jié)束,我們看到,在 print_message_function 函數(shù)循環(huán)了5遍結(jié)束以后,才打印出thread1 end

這是一個(gè)非常簡(jiǎn)單的例子,hello world級(jí)別的,只是用來(lái)演示Linux下C多線(xiàn)程的使用,在實(shí)際應(yīng)用中,由于多個(gè)線(xiàn)程往往會(huì)訪問(wèn)共享的資源(典型的是訪問(wèn)同一個(gè)全局變量),因此多個(gè)縣城間存在著競(jìng)爭(zhēng)的關(guān)系,這就需要對(duì)多個(gè)線(xiàn)程進(jìn)行同步,對(duì)其訪問(wèn)的數(shù)據(jù)予以保護(hù)。

多線(xiàn)程的同步與互斥

方式一:鎖

  • 在主線(xiàn)程中初始化鎖為解鎖狀態(tài)
    • pthread_mutex_t mutex;
    • pthread_mutex_init(&mutex, NULL);
  • 在編譯時(shí)初始化鎖為解鎖狀態(tài)
    • 鎖初始化 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  • 訪問(wèn)對(duì)象時(shí)的加鎖操作與解鎖操作
    • 加鎖 pthread_mutex_lock(&mutex)
    • 釋放鎖 pthread_mutex_unlock(&mutex)
不加鎖,數(shù)據(jù)不同步

我們先來(lái)看一個(gè)不加鎖,多個(gè)線(xiàn)程訪問(wèn)同一段數(shù)據(jù)的程序。

        
           1
        
        
          /*
        
        
          ************************************************************************


        
        
           2
        
        
              > File Name: no_mutex.c


        
        
           3
        
        
              > Author: couldtt(fyby)


        
        
           4
        
        
              > Mail: fuyunbiyi@gmail.com


        
        
           5
        
        
              > Created Time: 2013年12月15日 星期日 17時(shí)52分24秒


        
        
           6
        
        
           ***********************************************************************
        
        
          */
        
        
           7
        
        
           8
        
         #include <stdio.h>


        
           9
        
         #include <stdlib.h>


        
          10
        
         #include <pthread.h>


        
          11
        
        
          12
        
        
          int
        
         sharedi = 
        
          0
        
        
          ;


        
        
          13
        
        
          void
        
         increse_num(
        
          void
        
        
          );


        
        
          14
        
        
          15
        
        
          int
        
        
           main(){


        
        
          16
        
        
          int
        
        
           ret;


        
        
          17
        
        
              pthread_t thrd1, thrd2, thrd3;


        
        
          18
        
        
          19
        
             ret = pthread_create(&thrd1, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          20
        
             ret = pthread_create(&thrd2, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          21
        
             ret = pthread_create(&thrd3, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          22
        
        
          23
        
        
              pthread_join(thrd1, NULL);


        
        
          24
        
        
              pthread_join(thrd2, NULL);


        
        
          25
        
        
              pthread_join(thrd3, NULL);


        
        
          26
        
        
          27
        
             printf(
        
          "
        
        
          sharedi = %d\n
        
        
          "
        
        
          , sharedi);


        
        
          28
        
        
          29
        
        
          return
        
        
          0
        
        
          ;


        
        
          30
        
        
          31
        
        
          }


        
        
          32
        
        
          33
        
        
          void
        
         increse_num(
        
          void
        
        
          ) {


        
        
          34
        
        
          long
        
        
           i,tmp;


        
        
          35
        
        
          for
        
        (i=
        
          0
        
        ; i<=
        
          100000
        
        ; i++
        
          ) {


        
        
          36
        
                 tmp =
        
           sharedi;


        
        
          37
        
                 tmp = tmp + 
        
          1
        
        
          ;


        
        
          38
        
                 sharedi =
        
           tmp;


        
        
          39
        
        
              }


        
        
          40
        
         }
      

?

編譯

gcc no_mutex.c -onomutex -lpthread

運(yùn)行分析

從上圖可知,我們no_mutex每次的運(yùn)行結(jié)果都不一致,而且,運(yùn)行結(jié)果也不符合我們的預(yù)期,出現(xiàn)了錯(cuò)誤的結(jié)果。 原因就是三個(gè)線(xiàn)程競(jìng)爭(zhēng)訪問(wèn)全局變量sharedi,并且都沒(méi)有進(jìn)行相應(yīng)的同步。

舉個(gè)例子,當(dāng)線(xiàn)程thrd1訪問(wèn)到sharedi的時(shí)候,sharedi的值是1000,然后線(xiàn)程thrd1將sharedi的值累加到了1001,可是線(xiàn)程thrd2取到sharedi的時(shí)候,sharedi的值是1000,這時(shí)候線(xiàn)程thrd2對(duì)sharedi的值進(jìn)行加1操作,使其變成了1001,可是這個(gè)時(shí)候,sharedi的值已經(jīng)被線(xiàn)程thrd1加到1001了,然而,thrd2并不知道,所以又將sharedi的值賦為了1001,從而導(dǎo)致了結(jié)果的錯(cuò)誤。

這樣,我們就需要一個(gè)線(xiàn)程互斥的機(jī)制,來(lái)保護(hù)sharedi這個(gè)變量,讓同一時(shí)刻,只有一個(gè)線(xiàn)程能夠訪問(wèn)到這個(gè)變量,從而使它的值能夠保證正確的變化。

加鎖,數(shù)據(jù)同步

通過(guò)加鎖,保證sharedi變量在進(jìn)行變更的時(shí)候,只有一個(gè)線(xiàn)程能夠取到,并在在該線(xiàn)程對(duì)其進(jìn)行操作的時(shí)候,其它線(xiàn)程無(wú)法對(duì)其進(jìn)行訪問(wèn)。

        
           1
        
        
          /*
        
        
          ************************************************************************


        
        
           2
        
        
              > File Name: mutex.c 


        
        
           3
        
        
              > Author: couldtt(fyby)


        
        
           4
        
        
              > Mail: fuyunbiyi@gmail.com 


        
        
           5
        
        
              > Created Time: 2013年12月15日 星期日 17時(shí)52分24秒


        
        
           6
        
        
           ***********************************************************************
        
        
          */
        
        
           7
        
        
           8
        
         #include <stdio.h>


        
           9
        
         #include <stdlib.h>


        
          10
        
         #include <pthread.h>


        
          11
        
        
          12
        
        
          int
        
         sharedi = 
        
          0
        
        
          ;


        
        
          13
        
        
          void
        
         increse_num(
        
          void
        
        
          );


        
        
          14
        
        
          15
        
         pthread_mutex_t mutex =
        
           PTHREAD_MUTEX_INITIALIZER;


        
        
          16
        
        
          17
        
        
          int
        
        
           main(){


        
        
          18
        
        
          int
        
        
           ret;


        
        
          19
        
        
              pthread_t thrd1, thrd2, thrd3;


        
        
          20
        
        
          21
        
             ret = pthread_create(&thrd1, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          22
        
             ret = pthread_create(&thrd2, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          23
        
             ret = pthread_create(&thrd3, NULL, (
        
          void
        
         *
        
          )increse_num, NULL);


        
        
          24
        
        
          25
        
        
              pthread_join(thrd1, NULL);


        
        
          26
        
        
              pthread_join(thrd2, NULL);


        
        
          27
        
        
              pthread_join(thrd3, NULL);


        
        
          28
        
        
          29
        
             printf(
        
          "
        
        
          sharedi = %d\n
        
        
          "
        
        
          , sharedi);


        
        
          30
        
        
          31
        
        
          return
        
        
          0
        
        
          ;


        
        
          32
        
        
          33
        
        
          }


        
        
          34
        
        
          35
        
        
          void
        
         increse_num(
        
          void
        
        
          ) {


        
        
          36
        
        
          long
        
        
           i,tmp;


        
        
          37
        
        
          for
        
        (i=
        
          0
        
        ; i<=
        
          100000
        
        ; i++
        
          ) {


        
        
          38
        
        
          /*
        
        
          加鎖
        
        
          */
        
        
          39
        
        
          if
        
         (pthread_mutex_lock(&mutex) != 
        
          0
        
        
          ) {


        
        
          40
        
                    perror(
        
          "
        
        
          pthread_mutex_lock
        
        
          "
        
        
          );


        
        
          41
        
        
                     exit(EXIT_FAILURE);


        
        
          42
        
        
                  }


        
        
          43
        
                 tmp =
        
           sharedi;


        
        
          44
        
                 tmp = tmp + 
        
          1
        
        
          ;


        
        
          45
        
                 sharedi =
        
           tmp;


        
        
          46
        
        
          /*
        
        
          解鎖鎖
        
        
          */
        
        
          47
        
        
          if
        
         (pthread_mutex_unlock(&mutex) != 
        
          0
        
        
          ) {


        
        
          48
        
                     perror(
        
          "
        
        
          pthread_mutex_unlock
        
        
          "
        
        
          );


        
        
          49
        
        
                      exit(EXIT_FAILURE);


        
        
          50
        
        
                  }


        
        
          51
        
        
              }


        
        
          52
        
         }
      

?

結(jié)果分析

加鎖

這一次,我們的結(jié)果是正確的,鎖有效得保護(hù)了我們的數(shù)據(jù)安全。然而:

  1. 鎖保護(hù)的并不是我們的共享變量(或者說(shuō)是共享內(nèi)存),對(duì)于共享的內(nèi)存而言,用戶(hù)是無(wú)法直接對(duì)其保護(hù)的,因?yàn)槟鞘俏锢韮?nèi)存,無(wú)法阻止其他程序的代碼訪問(wèn)。事實(shí)上,鎖之所以對(duì)關(guān)鍵區(qū)域進(jìn)行了保護(hù),在本例中,是因?yàn)樗芯€(xiàn)程都遵循了一個(gè)規(guī)則,那就是在進(jìn)入關(guān)鍵區(qū)域錢(qián)加 同一把 鎖,在退出關(guān)鍵區(qū)域錢(qián)釋放 同一把

  2. 我們從上述運(yùn)行結(jié)果中可以看到,加鎖是會(huì)帶來(lái)額外的開(kāi)銷(xiāo)的,加鎖的代碼其運(yùn)行速度,明顯比不加鎖的要慢一些,所以,在使用鎖的時(shí)候,要合理,在不需要對(duì)關(guān)鍵區(qū)域進(jìn)行保護(hù)的場(chǎng)景下,我們便不要畫(huà)蛇添足,為其加鎖了

方式二:信號(hào)量

鎖有一個(gè)很明顯的缺點(diǎn),那就是它 只有兩種狀態(tài) :鎖定與不鎖定。

信號(hào)量本質(zhì)上是一個(gè)非負(fù)數(shù)的整數(shù)計(jì)數(shù)器,它也被用來(lái)控制對(duì)公共資源的訪問(wèn)。當(dāng)公共資源增加的時(shí)候,調(diào)用信號(hào)量增加函數(shù)sem_post()對(duì)其進(jìn)行增加,當(dāng)公共資源減少的時(shí)候,調(diào)用函數(shù)sem_wait()來(lái)減少信號(hào)量。其實(shí),我們是可以把鎖當(dāng)作一個(gè)0-1信號(hào)量的。

它們是在 /usr/include/semaphore.h 中進(jìn)行定義的,信號(hào)量的數(shù)據(jù)結(jié)構(gòu)為sem_t, 本質(zhì)上,它是一個(gè)long型整數(shù)

相關(guān)函數(shù)

在使用semaphore之前,我們需要先引入頭文件 #include <semaphore.h>

  • 初始化信號(hào)量:? int sem_init(sem_t *sem, int pshared, unsigned int value);
    • 成功返回0,失敗返回-1
    • 參數(shù)
    • sem:指向信號(hào)量結(jié)構(gòu)的一個(gè)指針
    • pshared: 不是0的時(shí)候,該信號(hào)量在進(jìn)程間共享,否則只能為當(dāng)前進(jìn)程的所有線(xiàn)程們共享
    • value:信號(hào)量的初始值
  • 信號(hào)量減1操作,當(dāng)sem=0的時(shí)候該函數(shù)會(huì)堵塞? int sem_wait(sem_t *sem);
    • 成功返回0,失敗返回-1
    • 參數(shù)
    • sem:指向信號(hào)量的一個(gè)指針
  • 信號(hào)量加1操作? int sem_post(sem_t *sem);
    • 參數(shù)與返回同上
  • 銷(xiāo)毀信號(hào)量? int sem_destroy(sem_t *sem);
    • 參數(shù)與返回同上
代碼示例
        
           1
        
        
          /*
        
        
          ************************************************************************


        
        
           2
        
        
              > File Name: sem.c


        
        
           3
        
        
              > Author: couldtt(fyby)


        
        
           4
        
        
              > Mail: fuyunbiyi@gmail.com 


        
        
           5
        
        
              > Created Time: 2013年12月15日 星期日 19時(shí)25分08秒


        
        
           6
        
        
           ***********************************************************************
        
        
          */
        
        
           7
        
        
           8
        
         #include <stdio.h>


        
           9
        
         #include <unistd.h>


        
          10
        
         #include <pthread.h>


        
          11
        
         #include <semaphore.h>


        
          12
        
        
          13
        
        
          #define
        
         MAXSIZE 10


        
          14
        
        
          15
        
        
          int
        
        
           stack[MAXSIZE];


        
        
          16
        
        
          int
        
         size = 
        
          0
        
        
          ;


        
        
          17
        
        
          sem_t sem;


        
        
          18
        
        
          19
        
        
          //
        
        
           生產(chǎn)者
        
        
          20
        
        
          void
        
         provide_data(
        
          void
        
        
          ) {


        
        
          21
        
        
          int
        
        
           i;


        
        
          22
        
        
          for
        
         (i=
        
          0
        
        ; i< MAXSIZE; i++
        
          ) {


        
        
          23
        
                 stack[i] =
        
           i;


        
        
          24
        
                 sem_post(&sem); 
        
          //
        
        
          為信號(hào)量加1
        
        
          25
        
        
              }


        
        
          26
        
        
          }


        
        
          27
        
        
          28
        
        
          //
        
        
           消費(fèi)者
        
        
          29
        
        
          void
        
         handle_data(
        
          void
        
        
          ) {


        
        
          30
        
        
          int
        
        
           i;


        
        
          31
        
        
          while
        
        ((i = size++) <
        
           MAXSIZE) {


        
        
          32
        
                 sem_wait(&
        
          sem);


        
        
          33
        
                 printf(
        
          "
        
        
          乘法: %d X %d = %d\n
        
        
          "
        
        , stack[i], stack[i], stack[i]*
        
          stack[i]);


        
        
          34
        
                 sleep(
        
          1
        
        
          );


        
        
          35
        
        
              }


        
        
          36
        
        
          }


        
        
          37
        
        
          38
        
        
          int
        
         main(
        
          void
        
        
          ) {


        
        
          39
        
        
          40
        
        
              pthread_t provider, handler;


        
        
          41
        
        
          42
        
             sem_init(&sem, 
        
          0
        
        , 
        
          0
        
        ); 
        
          //
        
        
          信號(hào)量初始化
        
        
          43
        
             pthread_create(&provider, NULL, (
        
          void
        
         *
        
          )handle_data, NULL);


        
        
          44
        
             pthread_create(&handler, NULL, (
        
          void
        
         *
        
          )provide_data, NULL);


        
        
          45
        
        
              pthread_join(provider, NULL);


        
        
          46
        
        
              pthread_join(handler, NULL);


        
        
          47
        
             sem_destroy(&sem); 
        
          //
        
        
          銷(xiāo)毀信號(hào)量
        
        
          48
        
        
          49
        
        
          return
        
        
          0
        
        
          ;


        
        
          50
        
         }
      

?

運(yùn)行結(jié)果:

因?yàn)樾盘?hào)量機(jī)制的存在,所以代碼在handle_data的時(shí)候,如果sem_wait(&sem)時(shí),sem為0,那么代碼會(huì)堵塞在sem_wait上面,從而避免了在stack中訪問(wèn)錯(cuò)誤的index而使整個(gè)程序崩潰。

參考資料

?
?
分類(lèi):? 讀書(shū)筆記

Step by Step:Linux C多線(xiàn)程編程入門(mén)(基本API及多線(xiàn)程的同步與互斥)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 灵武市| 兖州市| 满城县| 大姚县| 科尔| 大连市| 闵行区| 娄烦县| 轮台县| 儋州市| 八宿县| 宁乡县| 衡阳市| 六安市| 五常市| 南郑县| 西昌市| 崇州市| 沭阳县| 泰来县| 旺苍县| 合肥市| 若尔盖县| 黄浦区| 长葛市| 岳阳县| 大方县| 体育| 泰顺县| 乳源| 潞城市| 泰安市| 昌邑市| 高密市| 丹江口市| 奇台县| 南充市| 嵩明县| 白水县| 定远县| 寿光市|