C語言平行世界——線程

      網友投稿 848 2022-05-29

      假如你的程序一邊從網絡讀取數據,一邊向網絡發送數據。如何在代碼中同時執行幾個不同的任務?根據前面的知識,我們知道可以通過創建多幾個子進程來做這些事。但是創建進程很花時間,而且不同子進程之間共享數據很不方便。這時我們需要線程來幫我們解決這個問題。

      如何創建線程呢?

      我們有很多線程庫可以用,其中最流行的就是POSIX線程庫,也叫pthread 。可以在類Unix系統上使用。

      假設我想在獨立的線程中運行以下這兩個函數:

      void one(void *a){ int i = 0; for(i = 0;i<5;i++){ sleep(1); puts("one one one"); } return NULL; } void two(void *b){ int i = 0; for(i = 0;i < 5; i++){ sleep(1); puts("two two two"); } return NULL: }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      注意:線程函數的返回類型必須是void,void指針可以指向存儲器中任何類型的數據。*

      用pthread_create創建線程

      我們將創建兩個線程,每個線程都需要把信息保存在一個叫pthread_t的結構體中,然后就可以用pthread_create()創建并運行線程。

      pthread_t t0;//保存了線程的所有信息 pthread_t t1;//保存了線程的所有信息 if(pthread_create(&t0,NULL,one,NULL) == -1){//創建線程 error1("無法創建線程t0"); } if(pthread_create(&t1,NULL,two,NULL) == -1){//創建線程 error1("無法創建線程t1"); }

      1

      2

      3

      4

      5

      6

      7

      8

      代碼將以獨立線程運行這兩個函數。如果程序運行完這段代碼就結束了,線程也會隨之滅亡,因此程序必須等待線程結束。加上以下的代碼,就可以讓程序等線程執行完成,再結束。否則線程還沒來得及執行,程序就結束了。

      void* result; //函數返回 的void指針會保存在這里 if(pthread_join(t0,&result) == -1){ error1("無法收回線程t0"); } if(pthread_join(t1,&result) == -1){ error1("無法收回線程t1"); }

      1

      2

      3

      4

      5

      6

      7

      pthread_join()函數會等待線程結束并接收線程函數的返回值,并把它保存在一個void指針變量中。一旦兩個線程都結束了,程序就可以順利退出。

      編譯時要使用 pthread庫,所以必須在編譯程序時鏈接它:

      ~/Desktop/MyC$ gcc testThread.c -lpthread -o thread

      1

      運行程序:

      ~/Desktop/MyC$ ./thread one one one two two two two two two one one one two two two one one one two two two one one one two two two one one one

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      線程不安全

      線程最大的優點就是多個不同任務可以同時運行,并訪問相同數據,而不同任務可以訪問相同數據恰恰也是線程的缺點。怎么辦呢?我們可以通過互斥鎖來防止不同線程同時訪問共享資源,即不同線程不能同時讀取相同數據,并把它寫回。

      為了保護某段代碼的安全,我們需要創建互斥鎖:

      pthread_mutex_t a_lock = PTHREAD_MUTEX_INITIALIZER;

      1

      互斥鎖必須對所有可能發生沖突的線程可見,因此它必須是一個全局變量 。PTHREAD_MUTEX_INITIALIZER實際上是一個宏,當編譯器看到它時,就會插入創建互斥鎖的代碼。

      pthread_mutex_lock()函數只允許一個線程通過,其他線程運行到這行代碼時必須等待。當線程到達代碼的尾部就要調用pthread_mutex_unlock()釋放互斥鎖。

      pthread_mutex_lock(&a_lock);//含有共享數據的代碼從這里開始 .... //含有共享數據的代碼 pthread_mutex_unlock(&a_lock);//釋放互斥鎖,其他線程就可以入這段含有共享數據的代碼。

      1

      2

      3

      我們給出一個完整示例testThread.c:

      #include #include #include #include #include #include #include void error1(char *msg); void* sell_tickets(void *a); pthread_mutex_t a_lock = PTHREAD_MUTEX_INITIALIZER; int tickets = 500; int main(){ pthread_t threads[5]; long t; for(t = 0;t < 5;t++){ pthread_create(&threads[t],NULL,sell_tickets,(void*)t); } void* result; for(t = 0;t<5;t++){ pthread_join(threads[t],&result); } return 0; } void error1(char *msg){ fprintf(stderr,"%s:%s\n",msg,strerror(errno)); exit(1); } void* sell_tickets(void *a){ long thread_no = (long)a; int i; for(i = 0;i<100;i++){ pthread_mutex_lock(&a_lock);//含有共享數據的代碼從這里開始 tickets = tickets - 1; pthread_mutex_unlock(&a_lock);//釋放互斥鎖,其他線程就可以入這段含有共享數據的代碼。 } printf("Window No.%ld TICKETS:%d\n",thread_no,tickets); return NULL; }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      編譯運行:

      ~/Desktop/MyC$ gcc testThread.c -lpthread -o thread ~/Desktop/MyC$ ./thread Window No.0 TICKETS:398 Window No.1 TICKETS:300 Window No.2 TICKETS:200 Window No.3 TICKETS:100 Window No.4 TICKETS:0

      1

      2

      3

      4

      5

      6

      7

      線程函數可以接收一個void指針作為參數,并返回一個void指針值,通常你希望把某個整型值傳給線程,并讓它返回某個整型值,一種方法是用long,因為它的大小和void指針相同 ,可以把它保存在void指針變量中,如下面程序thread1.c:

      #include #include #include #include #include void* do_stuff(void* param); int main(){ pthread_t threads[3]; long t; for(t = 0;t<3;t++){ pthread_create(&threads[t],NULL,do_stuff,(void*)t);//將long型變量轉化為void指針類型 } void* result; for( t = 0;t<3;t++){ pthread_join(threads[t],&result); printf("Thread %ld returned %ld\n",t,(long)result);//result使用前先把它轉化為long } return 0; } void* do_stuff(void* param){ long thread_no = (long)param; printf("Thread number %ld\n",thread_no); return (void*)(thread_no+1); }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      C語言中平行的世界——線程

      18

      19

      20

      21

      22

      23

      24

      25

      編譯運行:

      ~/Desktop/MyC$ gcc thread1.c -lpthread -o thread1 ~/Desktop/MyC$ ./thread1 Thread number 0 Thread number 1 Thread number 2 Thread 0 returned 1 Thread 1 returned 2 Thread 2 returned 3

      1

      2

      3

      4

      5

      6

      7

      8

      操作系統怎樣運行多個線程呢?其實操作系統會在多個線程之間快速切換,看起來就好像在同時做多件事。

      線程不一定能讓程序更快,雖然線程可以幫助你利用機器上更多的處理器和核,但你還是需要控制代碼中互斥鎖的數量,用得太多互斥鎖,代碼可能會像單線程程序一樣慢。

      怎樣才能讓多線程程序運行得更快?首先要減少線程需要訪問的共享數據的數量。如果線程無需訪問很多共享數據,那么多個線程等一個線程的情況就會很少出現,速度就會大大提高。

      線程通常比進程更快,因為創建進程要比創建線程花更多時間。

      死鎖是如何發生的?假設你有兩個線程,它們都想得到互斥鎖A和B,如果第一個線程得到了A,第二個線程得到了B,這兩個線程就會陷入死鎖。因為第一個線程無法得到B,第二個線程無法得到A,它們都停滯不前。

      謝謝閱讀!

      C 語言 任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:推薦博文:Java對PDF文件的操作
      下一篇:《 Kubernetes進階實戰》一3.2.4資源配置清單格式文檔
      相關文章
      亚洲妇女水蜜桃av网网站| 亚洲午夜精品久久久久久app| 亚洲人成网亚洲欧洲无码久久| 亚洲AV无码日韩AV无码导航| 亚洲一区精彩视频| 久久精品国产精品亚洲精品| 亚洲精品永久在线观看| 亚洲AV午夜福利精品一区二区| 久久亚洲高清综合| 亚洲色偷偷综合亚洲av78| 亚洲AV人无码综合在线观看| 最新亚洲人成无码网www电影| 亚洲精品V欧洲精品V日韩精品 | 亚洲专区一路线二| 国产亚洲无线码一区二区| 亚洲午夜久久久久久久久电影网| 亚洲线精品一区二区三区影音先锋| 久久久久亚洲?V成人无码| 亚洲综合国产一区二区三区| 亚洲区小说区图片区QVOD| 亚洲va久久久噜噜噜久久| 亚洲视频在线观看一区| 亚洲AV网一区二区三区| 国产成人高清亚洲一区久久 | 亚洲av无码一区二区三区天堂| 亚洲狠狠ady亚洲精品大秀| 亚洲女人初试黑人巨高清| 亚洲精品第一国产综合野| 亚洲精品福利在线观看| 亚洲av日韩av激情亚洲| 久久久久久亚洲精品成人| 亚洲日本乱码一区二区在线二产线| 亚洲av无码国产综合专区| 亚洲精品无码av片| 亚洲一级特黄大片在线观看 | 国产亚洲人成网站在线观看| www.亚洲一区| 亚洲中文无码mv| 综合一区自拍亚洲综合图区| 亚洲毛片网址在线观看中文字幕| 国产精品亚洲一区二区无码|