日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多进程与多线程(1)

發(fā)布時間:2024/4/11 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多进程与多线程(1) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?說到多進(jìn)程和多線程,我就想起了《The art of Multiprocessor Programming》中的第一章的例子(我就看了第一章)

?

On the first day of your new job, your boss asks you to find all primes between?1 and 10^10(never mind why), using a parallel machine that supports ten concurrent?threads. This machine is rented by the minute, so the longer your program?takes, the more it costs. You want to make a good impression. What do?you do?

我對多線程編程不是很熟,所以想用這個例子學(xué)習(xí)一下多線程編程。

單線程編程

如果不會用線程,那么就用最簡單的單線程解決這個問題。

  • //example1.c
  • #include?<stdio.h>?
  • #include?<stdlib.h>?
  • #include?<math.h>?
  • long?long?isPrime(int?num)?
  • {?
  • ????long?long?i,?s;?
  • ????s?=?(long?long)sqrt(double(num));?
  • ????for(i?=?2;?i?<?s;?i++)?
  • ????????if(num?%?i?==?0)?
  • ????????????return?0;?
  • ????return?1;?
  • }?
  • int?main()?
  • {?
  • ????long?long?i,primes_count?=?0;?
  • ????for(i?=?1?;?i?<=?10000000000L;?i++)?
  • ????????primes_count?+=??isPrime(i);?
  • ????printf("%lld?primes);?
  • ????return?0;?
  • }?
  • 注意:編譯時加上-lm,gcc -lm example1.c ?; 打印long long整數(shù)要用%lld

    如果真用這段代碼跑10000000000L,估計幾個小時跑不完,幾天不知道能跑完嗎。我打算在16核的機(jī)器上跑一下,不過16核和單核一樣,因為是單線程。

    ?

    多線程方法1

    如果會使用線程,一個簡單的方法是10個線程平分這些數(shù)。

    -------------------------------------------------------------------------------------------

    pthread相關(guān)數(shù)據(jù)結(jié)構(gòu)和函數(shù)

    pthread_t 調(diào)用pthread_t返回的線程號,就是一個unsigned int;?

    int pthread_create(pthread_t *, pthread_attr_t *, ?void* ?(*) (void*) , void*);

    第一個參數(shù)是一個pthread_t,第二個是pthread_attr_t,具體看下面的用法,第三個是線程要運行的主函數(shù),第四個是要給這個函數(shù)的參數(shù)。

    (void*) (*) (void*) 是一個函數(shù)類型,就是類似于 void * ?run (void*)的函數(shù)。

    void pthread_exit() 線程退出

    int pthread_join(pthread_t *, void **) 主線程等待子線程退出,第二個參數(shù)直接用NULL就行

    ----------------------------------------------------------------------------------------------------------

  • //example2.c
  • #include?<stdio.h>?
  • #include?<stdlib.h>?
  • #include?<pthread.h>?
  • #include?<sys/types.h>?
  • #include?<unistd.h>?
  • #include?<math.h>?
  • long?long?isPrime(long?long?num)?
  • {?
  • ????long?long?i,?s;?
  • ????s?=?(long?long)sqrt((double)num);?
  • ????for(i?=?2;?i?<?s;?i++)?
  • ????????if(num?%?i?==?0)?
  • ????????????return?0;?
  • ????return?1;?
  • }?
  • ?
  • void?*?run(void?*?param)?
  • {?
  • ????long?long?start,end;?
  • ????long?long?i,primes_count?=?0;?
  • ????start?=(?(long?long*)param)[0];?
  • ????end??=(?(long?long*)param)[1];?
  • ????for(i?=?start?;?i?<?end;?i++)?
  • ????????primes_count?+=??isPrime(i);?
  • ????printf("Process?%d?Thread?%u?gets?%lld?primes?from?%lld?to?%lld\n",getpid(),(unsigned)pthread_self(),primes_count,start,end);?
  • ????pthread_exit(0);?
  • }?
  • ?
  • int?main()?
  • {?
  • ????pthread_t?tid[10];?
  • ????pthread_attr_t?attr;?
  • ????long?long?start_end[10][2];?
  • ????long?long??i;?
  • ????for(i?=?0;?i?<?10;?i++)?
  • ????{?
  • ????????start_end[i][0]?=?i*10000;?
  • ????????start_end[i][1]?=?(i+1)*10000;??
  • ????????pthread_attr_init(&attr);?
  • ????????pthread_create(&tid[i],&attr,run,(void*)start_end[i]);?
  • ????}?
  • ????for(i=?0;?i?<?10;?i++)?
  • ????????pthread_join(tid[i],NULL);?
  • ????return?0;?
  • }?
  • 注意:使用pthread編譯要加上-lpthread。 gcc -lm -lpthread example2.c

    運行結(jié)果:(不是10^10,只計算到100000)

    ------------------------------------------------------------------------------------------------

    遇到的問題:

    最開始我的主函數(shù)寫成這樣:

  • int?main()?
  • {?
  • ????pthread_t?tid[10];?
  • ????pthread_attr_t?attr;?
  • ????long?long?start_end[2];?
  • ????long?long?i;?
  • ????for(i?=?0;?i?<?10;?i++)?
  • ????{?
  • ????????start_end[0]?=?i*10000;?
  • ????????start_end[1]?=?(i+1)*10000;?
  • ????????pthread_attr_init(&attr);?
  • ????????pthread_create(&tid[i],&attr,run,(void*)start_end);?
  • ????????pthread_join(tid[i],NULL);?
  • ????}?
  • ????return?0;?
  • }?
  • 很明顯pthread_join地方寫錯了,這樣第一個進(jìn)程運行完了才會創(chuàng)建第二個,但是由于每個線程平分,所以我沒發(fā)現(xiàn)結(jié)果有異常。

    寫第三個程序時pthread_join也寫錯了位置,這才發(fā)現(xiàn)。但是我將pthread_join放到后面時,發(fā)現(xiàn)每個線程處理的數(shù)據(jù)段都是90000-100000,沒找到原因,因此我的start_end改成了二維數(shù)組,這樣各個線程就不會干擾了,具體的原因以后再研究。

    --------------------------------------------------------------------------------------

    這個程序應(yīng)該比第一個快,但是判斷第一段數(shù)據(jù)的線程使用的時間肯定沒有最后一段使用的時間的千分之一,最后9個人看一個人干活,我突然想到了什么。。。

    多線程方法2

    多線程的目的就是壓榨計算資源。我們可以使用下面的方法。

    每個線程取一個數(shù),然后判斷,判斷完了繼續(xù)取下一個,讓每個線程都不停的干活

    線程取了1,判斷,線程2取2判斷,線程3取3,這時線程1干完了,接著取4,線程2又取5。。。。

  • #include?<stdio.h>?
  • #include?<stdlib.h>?
  • #include?<pthread.h>?
  • #include?<sys/types.h>?
  • #include?<unistd.h>?
  • #include?<math.h>?
  • long?long?number?=?1;?//每個線程先取數(shù),再把這個數(shù)加1
  • long?long?isPrime(long?long?num)?
  • {?
  • ????long?long?i,?s;?
  • ????s?=?(long?long)sqrt((double)num);?
  • ????for(i?=?2;?i?<?s;?i++)?
  • ????????if(num?%?i?==?0)?
  • ????????????return?0;?
  • ????return?1;?
  • }?
  • static?pthread_mutex_t?mutex;?
  • void?*?run(void?*?param)?
  • {?
  • ????long?long?primes_count=0;?
  • ????long?long?i?=?1;?
  • ????while(i?<?100000)?
  • ????{?
  • //要使用鎖
  • ????????pthread_mutex_lock(&mutex);?
  • ????????i?=?number;?
  • ????????number?++;?
  • ????????pthread_mutex_unlock(&mutex);?
  • ????????primes_count?+=??isPrime(i);?
  • ????}?
  • ????printf("Thread?%u?gets?%lld?primes\n",(unsigned??int)pthread_self(),primes_count);?
  • ????pthread_exit(0);?
  • }?
  • ?
  • ?int?main()?
  • {?
  • ????pthread_t?tid[10];?
  • ????pthread_attr_t?attr;?
  • ????pthread_mutex_init(&mutex,NULL);?
  • ????int?i;?
  • ?
  • ????for(i?=?0;?i?<?10;?i++)?
  • ????{?
  • ????????pthread_attr_init(&attr);?
  • ????????pthread_attr_setscope?(&attr,?PTHREAD_SCOPE_SYSTEM);?
  • ????????pthread_create(&tid[i],&attr,run,NULL);?
  • ????????//pthread_join(tid[i],NULL);?一開始把join放這,結(jié)果只有第一個線程干活,找了好久才發(fā)現(xiàn)位置錯了
  • ????}?
  • ????for(i?=?0;?i?<?10;?i++)?
  • ????????pthread_join(tid[i],NULL);?
  • ????return?0;?
  • }?
  • 運行結(jié)果:

    多進(jìn)程實現(xiàn)

    用多線程能完成的,多進(jìn)程也可以。

  • #include?<stdio.h>?
  • #include?<stdlib.h>?
  • #include?<pthread.h>?
  • #include?<sys/types.h>?
  • #include?<unistd.h>?
  • #include?<math.h>?
  • #include?<sys/ipc.h>?
  • #include?<sys/shm.h>?
  • #include?<errno.h>?
  • #include?<string.h>?
  • long?long?isPrime(long?long?num)?
  • {?
  • ????long?long?i,?s;?
  • ????s?=?(long?long)sqrt((double)num);?
  • ????for(i?=?2;?i?<?s;?i++)?
  • ????????if(num?%?i?==?0)?
  • ????????????return?0;?
  • ????return?1;?
  • }?
  • ?
  • int?main()?
  • {?
  • ????pid_t?pid[10];?
  • ????int?shmid;?
  • ????long?long??i,primes_count=0;?
  • ????long?long?*?addr;?
  • ????shmid?=?shmget(IPC_PRIVATE,4096,IPC_CREAT|0600);?
  • ????if(shmid?<?0)?
  • ????{?
  • ????????printf("get?shared?memory?failed\n");?
  • ????????exit(1);?
  • ????}?
  • ????addr?=?(long?long*)?shmat(shmid,0,0);?
  • ????*addr?=?1;?
  • ????for(i?=?0;?i?<?3;?i++)?
  • ????????fork();?
  • ????while(i?<?100000)?
  • ????{?
  • ????????i?=?(*addr);?
  • ????????(*addr)?++;?
  • ????????primes_count?+=?isPrime(i);?
  • ????}?
  • ????printf("pid?%d?get?%lld?primes\n",getpid(),primes_count);?
  • ????return?0;?
  • }?
  • ?

    注意:(1)使用循環(huán)fork,那么子進(jìn)程還會fork,因此fork三次就得到了8個進(jìn)程,在fork就16個進(jìn)程了。要想產(chǎn)生10個進(jìn)程,可以在主進(jìn)程里寫10個fork語句,還得寫很多if(fork()==0)語句,懶得寫,就直接用循環(huán)了。加上主進(jìn)程一個8個,先生完了孩子再干活,生完之后都成了兄弟,一起干。

    ? ? ? ? ? ?(2)這個程序有個嚴(yán)重的問題,使用了共享內(nèi)存,但是沒有使用同步機(jī)制,沒有鎖,挺麻煩的,不會用,就沒寫。結(jié)果可能不正確。

    ? 運行結(jié)果:

    ?小結(jié)

    我就截幾個圖

    這是單線程的,CPU使用了100%,看來也不錯,但是我的CPU有200%,有兩個核(我用的虛擬機(jī),可以分16個核哦親),因此單線程不能充分利用計算資源。

    多線程的把我的CPU都用完了。哈哈

    多進(jìn)程的呢?算一算,也是200%。

    其實在Linux里面線程也是進(jìn)程,稱為LWP(Light Weighted Process),只不過在生成的時候參數(shù)不同。在以后的文章里會深入研究。

    ?

    轉(zhuǎn)載于:https://blog.51cto.com/nxlhero/1075979

    總結(jié)

    以上是生活随笔為你收集整理的多进程与多线程(1)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。