qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請?jiān)L問 http://qaseven.github.io/

          多線程的那點(diǎn)兒事(基礎(chǔ)篇)

          多線程編程是現(xiàn)代軟件技術(shù)中很重要的一個(gè)環(huán)節(jié)。要弄懂多線程,這就要牽涉到多進(jìn)程?當(dāng)然,要了解到多進(jìn)程,就要涉及到操作系統(tǒng)。不過大家也不要緊張,聽我慢慢道來。這其中的環(huán)節(jié)其實(shí)并不復(fù)雜。

            (1)單CPU下的多線程

            在沒有出現(xiàn)多核CPU之前,我們的計(jì)算資源是唯一的。如果系統(tǒng)中有多個(gè)任務(wù)要處理的話,那么就需要按照某種規(guī)則依次調(diào)度這些任務(wù)進(jìn)行處理。什么規(guī)則呢?可以是一些簡單的調(diào)度方法,比如說

            1)按照優(yōu)先級(jí)調(diào)度

            2)按照FIFO調(diào)度

            3)按照時(shí)間片調(diào)度等等

            當(dāng)然,除了CPU資源之外,系統(tǒng)中還有一些其他的資源需要共享,比如說內(nèi)存、文件、端口、socket等。既然前面說到系統(tǒng)中的資源是有限的,那么獲取這些資源的最小單元體是什么呢,其實(shí)就是進(jìn)程。

            舉個(gè)例子來說,在linux上面每一個(gè)享有資源的個(gè)體稱為task_struct,實(shí)際上和我們說的進(jìn)程是一樣的。我們可以看看task_struct(linux 0.11代碼)都包括哪些內(nèi)容

        1. struct task_struct {  
        2. /* these are hardcoded - don't touch */  
        3.     long state; /* -1 unrunnable, 0 runnable, >0 stopped */  
        4.     long counter;  
        5.     long priority;  
        6.     long signal;  
        7.     struct sigaction sigaction[32];  
        8.     long blocked;   /* bitmap of masked signals */  
        9. /* various fields */  
        10.     int exit_code;  
        11.     unsigned long start_code,end_code,end_data,brk,start_stack;  
        12.     long pid,father,pgrp,session,leader;  
        13.     unsigned short uid,euid,suid;  
        14.     unsigned short gid,egid,sgid;  
        15.     long alarm;  
        16.     long utime,stime,cutime,cstime,start_time;  
        17.     unsigned short used_math;  
        18. /* file system info */  
        19.     int tty;        /* -1 if no tty, so it must be signed */  
        20.     unsigned short umask;  
        21.     struct m_inode * pwd;  
        22.     struct m_inode * root;  
        23.     struct m_inode * executable;  
        24.     unsigned long close_on_exec;  
        25.     struct file * filp[NR_OPEN];  
        26. /* ldt for this task 0 - zero 1 - cs 2 - ds&ss */  
        27.     struct desc_struct ldt[3];  
        28. /* tss for this task */  
        29.     struct tss_struct tss;  
        30. };
        31.   每一個(gè)task都有自己的pid,在系統(tǒng)中資源的分配都是按照pid進(jìn)行處理的。這也就說明,進(jìn)程確實(shí)是資源分配的主體。

            這時(shí)候,可能有朋友會(huì)問了,既然task_struct是資源分配的主體,那為什么又出來thread?為什么系統(tǒng)調(diào)度的時(shí)候是按照thread調(diào)度,而不是按照進(jìn)程調(diào)度呢?原因其實(shí)很簡單,進(jìn)程之間的數(shù)據(jù)溝通非常麻煩,因?yàn)槲覀冎园堰@些進(jìn)程分開,不正是希望它們之間不要相互影響嘛。

            假設(shè)是兩個(gè)進(jìn)程之間數(shù)據(jù)傳輸,那么需要如果需要對共享數(shù)據(jù)進(jìn)行訪問需要哪些步驟呢

            1)創(chuàng)建共享內(nèi)存

            2)訪問共享內(nèi)存->系統(tǒng)調(diào)用->讀取數(shù)據(jù)

            3)寫入共享內(nèi)存->系統(tǒng)調(diào)用->寫入數(shù)據(jù)

           要是寫個(gè)代碼,大家可能就更明白了

        32. #include <unistd.h>   
        33. #include <stdio.h>   
        34.   
        35. int value = 10;  
        36.   
        37. int main(int argc, char* argv[])  
        38. {  
        39.     int pid = fork();  
        40.     if(!pid){  
        41.         Value = 12;  
        42.         return 0;  
        43.     }  
        44.     printf("value = %d\n", value);  
        45.     return 1;  
        46. }
        47.   上面的代碼是一個(gè)創(chuàng)建子進(jìn)程的代碼,我們發(fā)現(xiàn)打印的value數(shù)值還是10。盡管中間創(chuàng)建了子進(jìn)程,修改了value的數(shù)值,但是我們發(fā)現(xiàn)打印下來的數(shù)值并沒有發(fā)生改變,這就說明了不同的進(jìn)程之間內(nèi)存上是不共享的。

            那么,如果修改成thread有什么好處呢?其實(shí)最大的好處就是每個(gè)thread除了享受單獨(dú)cpu調(diào)度的機(jī)會(huì),還能共享每個(gè)進(jìn)程下的所有資源。要是調(diào)度的單位是進(jìn)程,那么每個(gè)進(jìn)程只能干一件事情,但是進(jìn)程之間是需要相互交互數(shù)據(jù)的,而進(jìn)程之間的數(shù)據(jù)都需要系統(tǒng)調(diào)用才能應(yīng)用,這在無形之中就降低了數(shù)據(jù)的處理效率。

            (2)多核CPU下的多線程

            沒有出現(xiàn)多核之前,我們的CPU實(shí)際上是按照某種規(guī)則對線程依次進(jìn)行調(diào)度的。在某一個(gè)特定的時(shí)刻,CPU執(zhí)行的還是某一個(gè)特定的線程。然而,現(xiàn)在有了多核CPU,一切變得不一樣了,因?yàn)樵谀骋粫r(shí)刻很有可能確實(shí)是n個(gè)任務(wù)在n個(gè)核上運(yùn)行。我們可以編寫一個(gè)簡單的open mp測試一下,如果還是一個(gè)核,運(yùn)行的時(shí)間就應(yīng)該是一樣的。

        48. #include <omp.h>   
        49. #define MAX_VALUE 10000000   
        50.   
        51. double _test(int value)  
        52. {  
        53.     int index;  
        54.     double result;  
        55.   
        56.     result = 0.0;  
        57.     for(index = value + 1; index < MAX_VALUE; index +=2 )  
        58.         result += 1.0 / index;  
        59.   
        60.     return result;  
        61. }  
        62.   
        63. void test()  
        64. {  
        65.     int index;  
        66.     int time1;  
        67.     int time2;  
        68.     double value1,value2;  
        69.     double result[2];  
        70.   
        71.     time1 = 0;  
        72.     time2 = 0;  
        73.   
        74.     value1 = 0.0;  
        75.     time1 = GetTickCount();  
        76.     for(index = 1; index < MAX_VALUE; index ++)  
        77.         value1 += 1.0 / index;  
        78.   
        79.     time1 = GetTickCount() - time1;  
        80.   
        81.     value2 = 0.0;  
        82.     memset(result , 0, sizeof(double) * 2);  
        83.     time2 = GetTickCount();  
        84.   
        85. #pragma omp parallel for   
        86.     for(index = 0; index < 2; index++)  
        87.         result[index] = _test(index);  
        88.   
        89.     value2 = result[0] + result[1];  
        90.     time2 = GetTickCount() - time2;  
        91.   
        92.     printf("time1 = %d,time2 = %d\n",time1,time2);  
        93.     return;  
        94. }
        95.   (3)多線程編程

            為什么要多線程編程呢?這其中的原因很多,我們可以舉例解決

            1)有的是為了提高運(yùn)行的速度,比如多核cpu下的多線程

            2)有的是為了提高資源的利用率,比如在網(wǎng)絡(luò)環(huán)境下下載資源時(shí),時(shí)延常常很高,我們可以通過不同的thread從不同的地方獲取資源,這樣可以提高效率

            3)有的為了提供更好的服務(wù),比如說是服務(wù)器

            4)其他需要多線程編程的地方等等

          posted on 2011-12-08 14:28 順其自然EVO 閱讀(174) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          <2011年12月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 霸州市| 全南县| 龙州县| 尼玛县| 长垣县| 延吉市| 四平市| 拜城县| 宿迁市| 九江县| 县级市| 科尔| 镇赉县| 桐柏县| 阳朔县| 自治县| 鹿邑县| 濮阳县| 盘锦市| 孟村| 大新县| 扶沟县| 故城县| 乌什县| 周宁县| 拉孜县| 确山县| 若羌县| 清新县| 库伦旗| 天柱县| 周口市| 嘉峪关市| 阳江市| 南木林县| 林州市| 福贡县| 离岛区| 大宁县| 洞头县| 泰来县|