亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
12下一頁
最近訪問板塊 發(fā)新帖
查看: 4480 | 回復(fù): 12
打印 上一主題 下一主題

[C] 如何在多線程中保證結(jié)果輸出順序與數(shù)據(jù)輸入順序一樣? [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2016-08-18 11:01 |只看該作者 |倒序?yàn)g覽
現(xiàn)假定僅一線程讀取輸入數(shù)據(jù),三個(gè)(或任意個(gè))Workers同時(shí)分別地處理數(shù)據(jù),另一個(gè)線程輸出已處理的數(shù)據(jù),但要求其輸出數(shù)據(jù)的順序與輸入數(shù)據(jù)順序一致。為簡單計(jì),例如,若輸入1,2,3,…N個(gè)整數(shù),多線程處理后,輸出的順序仍為1,2,3,…N。

下面簡單程序嘗試實(shí)現(xiàn)以上目標(biāo),但未成功,大多數(shù)情況下,輸出是正確的。有時(shí)程序凍結(jié)某點(diǎn),沒有全部輸出所有數(shù)據(jù)。請教各位還需要什么同步機(jī)制才能保證任何情況下全部依序輸岀?謝謝!

  1. include <pthread.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <semaphore.h>
  7. #include <errno.h>
  8. #define check(rc, msg) { \
  9.         if (!rc) \
  10.           fprintf(stderr, "%s failed \n", msg), exit(1); \
  11. }

  12. #define dbg(...)  fprintf(stderr,__VA_ARGS__)

  13. #define NBUFF       16      /* number of slots */
  14. #define NP          1       /* number of producers */
  15. #define NC          3       /* number of consumers */

  16. int widx = 0, ridx = 0, qoidx = 0, qridx = 0;

  17. struct rec {
  18.     struct {
  19.     int    data;
  20.     size_t seq;
  21.     } buff[NBUFF];
  22.     sem_t full;           /* number of full slots  */
  23.     sem_t empty;          /* number of empty slots */
  24.     sem_t rmut;           /* mutual exclusion to shared data */
  25.     sem_t wmut;           /* mutual exclusion to shared data */
  26. } shared, sha2;

  27. size_t seq = 1;
  28. void calc(size_t lineNbr, int val) {
  29.         /* do something with.., ie. val */
  30.         usleep(rand()%307);

  31.         sem_wait(&sha2.empty);
  32.         sem_wait(&sha2.wmut);
  33.         sha2.buff[qoidx].data = val;
  34.         sha2.buff[qoidx].seq = lineNbr;
  35.         dbg("QIn : %ld -> %d \n", sha2.buff[qoidx].seq, sha2.buff[qoidx].data);
  36.         qoidx = (qoidx+1) % NBUFF;
  37.         sem_post(&sha2.full);
  38.         sem_post(&sha2.wmut);
  39. }

  40. size_t cnt = 1; int fg=0;
  41. void* seqOut(void* arg) {
  42.       for(int i=0;i<=seq && cnt<seq;i++) {
  43.          //dbg("..Loop 1.. \n");
  44.          sem_wait(&sha2.full);
  45.          fg=0;
  46.          while(!fg) {
  47.          if(sha2.buff[qridx].seq == cnt) {
  48.             fprintf(stderr,"Output : {%ld: %d}\n", cnt, sha2.buff[qridx].data);
  49.             cnt++;
  50.             fg=1;
  51.             sem_post(&sha2.empty);
  52.             //dbg("..Loop 2.. \n");
  53.          }
  54.          else {
  55.             fg=0;
  56.             qridx = (qridx+1) % NBUFF;
  57.             //dbg("..Loop 3..qridx=%d \n", qridx);
  58.           }
  59.          }
  60.          qridx = (qridx+1) % NBUFF;
  61.     }
  62. return NULL;
  63. }

  64. void *Producer(void *arg) {
  65.      int i;

  66.      for(i=1; i<=50; i++) {
  67.             /* If no empty slot, wait */
  68.             sem_wait(&shared.empty);

  69.             shared.buff[widx].data = i;
  70.             shared.buff[widx].seq = seq++;
  71.             //fprintf(stderr,"Read : [%ld -> %d] \n", shared.buff[widx].seq, shared.buff[widx].data);
  72.             widx = (widx+1)%NBUFF;

  73.             sem_post(&shared.full);
  74.        }
  75.      for(int i=0; i<NC; i++) {
  76.             sem_wait(&shared.empty);
  77.               shared.buff[widx].data = -999;
  78.               widx = (widx+1)%NBUFF;
  79.             sem_post(&shared.full);
  80.      }
  81.   return NULL;
  82. }

  83. void *Consumer(void *arg) {
  84.     int n, lineNbr;

  85.     while (1) {
  86.         sem_wait(&shared.full);
  87.         /* If another thread uses the buffer, wait */
  88.         sem_wait(&shared.rmut);

  89.         if(shared.buff[ridx].data == -999) {
  90.           ridx = (ridx+1)%NBUFF;
  91.           sem_post(&shared.empty);
  92.           sem_post(&shared.rmut);
  93.           return NULL;
  94.         }

  95.         n = shared.buff[ridx].data;
  96.         lineNbr = shared.buff[ridx].seq;

  97.         ridx = (ridx+1)%NBUFF;

  98.         sem_post(&shared.empty);
  99.         sem_post(&shared.rmut);
  100.         calc(lineNbr, n);
  101.     }

  102.     return NULL;
  103. }

  104. int main(int argc, char** argv) {
  105.     pthread_t idP[NP],    idC[NC],    seqThr;
  106.     int       indexP[NP], indexC[NC], i;

  107.     check( sem_init(&shared.full, 0, 0 )== 0, "init full err");
  108.     check( sem_init(&sha2.full, 0, 0 )== 0, "init full2 err");
  109.     check( sem_init(&shared.empty, 0, NBUFF) == 0, "init empty err");
  110.     check( sem_init(&sha2.empty, 0, NBUFF) == 0, "init empty2 err");
  111.     check( sem_init(&shared.rmut, 0, 1) == 0, "init reader mutex err");
  112.     check( sem_init(&sha2.rmut, 0, 1) == 0, "init reader2 mutex err");
  113.     check( sem_init(&shared.wmut, 0, 1) == 0, "init writer mutex err");
  114.     check( sem_init(&sha2.wmut, 0, 1) == 0, "init writer2 mutex err");
  115.     for (i = 0; i < NP; i++) {
  116.         indexP[i] = i+1;
  117.         check( pthread_create(&idP[i], NULL, Producer, &indexP[i]) == 0, "create Pth err");
  118.     }

  119.     for (i = 0; i < NC; i++) {
  120.         indexC[i] = i+1;
  121.         check( pthread_create(&idC[i], NULL, Consumer, &indexC[i]) == 0, "create Cth err");
  122.     }
  123.     check( pthread_create(&seqThr, NULL, seqOut, NULL) == 0, "create seqThr err");

  124.     for (i = 0; i < NP; i++) {
  125.         check( pthread_join(idP[i], NULL) == 0, "join Pth err");
  126.     }

  127.     for (i = 0; i < NC; i++) {
  128.         check( pthread_join(idC[i], NULL) == 0, "join Cth err");
  129.     }

  130.     check( pthread_join(seqThr, NULL) == 0, "join seqThr err");

  131.     check( sem_destroy(&shared.full) == 0, "destroy full err");
  132.     check( sem_destroy(&sha2.full) == 0, "destroy full2 err");
  133.     check( sem_destroy(&shared.empty) == 0, "destroy empty err");
  134.     check( sem_destroy(&sha2.empty) == 0, "destroy empty2 err");
  135.     check( sem_destroy(&shared.rmut) == 0, "destroy rdmutex err");
  136.     check( sem_destroy(&sha2.rmut) == 0, "destroy rdmutex2 err");
  137.     check( sem_destroy(&shared.wmut) == 0, "destroy wrmutex err");
  138.     check( sem_destroy(&sha2.wmut) == 0, "destroy wrmutex2 err");
  139.     fprintf(stderr,"all OK \n");
  140.     return 0;
  141. }
  142.                                                                                                                                     168,1         Bot
復(fù)制代碼

論壇徽章:
0
2 [報(bào)告]
發(fā)表于 2016-08-18 11:03 |只看該作者
一種可能輸出,正確的.
QIn : 1 -> 1
Output : {1: 1}
QIn : 2 -> 2
Output : {2: 2}
QIn : 4 -> 4
QIn : 3 -> 3
Output : {3: 3}
Output : {4: 4}
QIn : 5 -> 5
Output : {5: 5}
QIn : 6 -> 6
QIn : 7 -> 7
Output : {6: 6}
Output : {7: 7}
QIn : 8 -> 8
Output : {8: 8}
QIn : 10 -> 10
QIn : 11 -> 11
QIn : 12 -> 12
QIn : 9 -> 9
Output : {9: 9}
Output : {10: 10}
Output : {11: 11}
Output : {12: 12}
QIn : 13 -> 13
Output : {13: 13}
QIn : 16 -> 16
QIn : 14 -> 14
Output : {14: 14}
Output : {15: 15}
QIn : 15 -> 15
Output : {16: 16}
QIn : 17 -> 17
Output : {17: 17}
QIn : 20 -> 20
QIn : 18 -> 18
Output : {18: 18}
Output : {19: 19}
QIn : 19 -> 19
Output : {20: 20}
QIn : 21 -> 21
Output : {21: 21}
QIn : 23 -> 23
QIn : 24 -> 24
QIn : 22 -> 22
Output : {22: 22}
Output : {23: 23}
QIn : 27 -> 27
Output : {24: 24}
QIn : 26 -> 26
QIn : 28 -> 28
QIn : 25 -> 25
Output : {25: 25}
Output : {26: 26}
Output : {27: 27}
Output : {28: 28}
QIn : 32 -> 32
QIn : 30 -> 30
QIn : 31 -> 31
QIn : 29 -> 29
Output : {29: 29}
Output : {30: 30}
Output : {31: 31}
Output : {32: 32}
QIn : 34 -> 34
QIn : 33 -> 33
Output : {33: 33}
Output : {34: 34}
QIn : 36 -> 36
QIn : 35 -> 35
Output : {35: 35}
Output : {36: 36}
QIn : 37 -> 37
Output : {37: 37}
QIn : 38 -> 38
Output : {38: 38}
QIn : 41 -> 41
QIn : 42 -> 42
QIn : 39 -> 39
Output : {39: 39}
QIn : 40 -> 40
Output : {40: 40}
Output : {41: 41}
Output : {42: 42}
QIn : 43 -> 43
Output : {43: 43}
QIn : 44 -> 44
Output : {44: 44}
QIn : 47 -> 47
QIn : 48 -> 48
QIn : 45 -> 45
Output : {45: 45}
QIn : 46 -> 46
Output : {46: 46}
Output : {47: 47}
Output : {48: 48}
QIn : 49 -> 49
Output : {49: 49}
QIn : 50 -> 50
Output : {50: 50}
all OK

論壇徽章:
0
3 [報(bào)告]
發(fā)表于 2016-08-18 11:06 |只看該作者
另一種可能輸出,不正確的.
QIn : 1 -> 1
Output : {1: 1}
QIn : 2 -> 2
Output : {2: 2}
QIn : 3 -> 3
Output : {3: 3}
QIn : 4 -> 4
Output : {4: 4}
QIn : 5 -> 5
Output : {5: 5}
QIn : 7 -> 7
QIn : 6 -> 6
Output : {6: 6}
Output : {7: 7}
QIn : 8 -> 8
Output : {8: 8}
QIn : 11 -> 11
QIn : 9 -> 9
QIn : 10 -> 10
QIn : 12 -> 12
Output : {9: 9}
Output : {10: 10}
Output : {11: 11}
Output : {12: 12}
QIn : 16 -> 16
QIn : 13 -> 13
Output : {13: 13}
Output : {14: 14}
QIn : 14 -> 14
QIn : 17 -> 17
QIn : 18 -> 18
QIn : 20 -> 20
QIn : 19 -> 19
QIn : 23 -> 23
QIn : 21 -> 21
QIn : 22 -> 22
QIn : 24 -> 24
QIn : 27 -> 27
QIn : 25 -> 25
QIn : 26 -> 26
QIn : 28 -> 28
QIn : 30 -> 30
QIn : 31 -> 31
QIn : 29 -> 29
程序凍結(jié),沒有全部輸出所有數(shù)據(jù)

論壇徽章:
15
射手座
日期:2014-11-29 19:22:4915-16賽季CBA聯(lián)賽之青島
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16賽季CBA聯(lián)賽之四川
日期:2017-02-07 21:08:572015年亞冠紀(jì)念徽章
日期:2015-11-06 12:31:58每日論壇發(fā)貼之星
日期:2015-08-04 06:20:00程序設(shè)計(jì)版塊每日發(fā)帖之星
日期:2015-08-04 06:20:00程序設(shè)計(jì)版塊每日發(fā)帖之星
日期:2015-07-12 22:20:002015亞冠之浦和紅鉆
日期:2015-07-08 10:10:132015亞冠之大阪鋼巴
日期:2015-06-29 11:21:122015亞冠之廣州恒大
日期:2015-05-22 21:55:412015年亞洲杯之伊朗
日期:2015-04-10 16:28:25
4 [報(bào)告]
發(fā)表于 2016-08-18 15:09 |只看該作者
本帖最后由 yulihua49 于 2016-08-18 15:14 編輯

沒辦法。并行數(shù)據(jù)處理的必定無序。數(shù)據(jù)的序就靠索引,用索引定序吧。
處理結(jié)果存入數(shù)據(jù)庫,排序后輸出。

或者,每個(gè)數(shù)據(jù)配個(gè)順序號,處理完了按順序號插入map,然后遍歷map輸出。
如果是分布處理,數(shù)據(jù)分布在多個(gè)服務(wù)器上,只有存入數(shù)據(jù)庫一種方法比較簡單。

論壇徽章:
0
5 [報(bào)告]
發(fā)表于 2016-08-18 21:14 |只看該作者
不會吧?我看過 python / golang code, 他們 都做到了,而且與無序輸出運(yùn)行時(shí)間差很少!現(xiàn)只考慮在一臺機(jī)上運(yùn)行。C++碼也歡迎!

論壇徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16賽季CBA聯(lián)賽之江蘇
日期:2017-11-27 11:42:3515-16賽季CBA聯(lián)賽之八一
日期:2017-04-12 14:26:2815-16賽季CBA聯(lián)賽之吉林
日期:2016-08-20 10:43:1215-16賽季CBA聯(lián)賽之廣夏
日期:2016-06-23 09:53:58程序設(shè)計(jì)版塊每日發(fā)帖之星
日期:2016-02-11 06:20:00程序設(shè)計(jì)版塊每日發(fā)帖之星
日期:2016-02-09 06:20:0015-16賽季CBA聯(lián)賽之上海
日期:2015-12-25 16:40:3515-16賽季CBA聯(lián)賽之廣夏
日期:2015-12-22 09:39:36程序設(shè)計(jì)版塊每日發(fā)帖之星
日期:2015-08-24 06:20:002015亞冠之德黑蘭石油
日期:2015-08-07 09:57:302015年辭舊歲徽章
日期:2015-03-03 16:54:15
6 [報(bào)告]
發(fā)表于 2016-08-19 11:36 |只看該作者
本帖最后由 lxyscls 于 2016-08-19 11:41 編輯
mjus 發(fā)表于 2016-08-18 21:14
不會吧?我看過 python / golang code, 他們 都做到了,而且與無序輸出運(yùn)行時(shí)間差很少!現(xiàn)只考慮在一臺機(jī)上 ...


你的N是多少?50?50和50log50可不就不差太多

map的方法前面有人講過了,再具體一點(diǎn)unordered_map

worker thread 處理完后insert,key是輸入序號

output thread while(1)根據(jù)序號get,get到就說明已插入,沒有就retry

論壇徽章:
0
7 [報(bào)告]
發(fā)表于 2016-08-19 21:34 |只看該作者
你不要想太簡單,這里只為簡單示例,實(shí)際上N為千萬級,或億上大數(shù)據(jù)處理的!用map足夠安全嗎?關(guān)鍵怎樣處理同步問題

論壇徽章:
59
2015年亞洲杯之約旦
日期:2015-01-27 21:27:392015年亞洲杯之日本
日期:2015-02-06 22:09:41拜羊年徽章
日期:2015-03-03 16:15:432015年辭舊歲徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:50:282015元宵節(jié)徽章
日期:2015-03-06 15:50:392015年亞洲杯之阿聯(lián)酋
日期:2015-03-19 17:39:302015年亞洲杯之中國
日期:2015-03-23 18:52:23巳蛇
日期:2014-12-14 22:44:03雙子座
日期:2014-12-10 21:39:16處女座
日期:2014-12-02 08:03:17天蝎座
日期:2014-07-21 19:08:47
8 [報(bào)告]
發(fā)表于 2016-08-19 22:00 |只看該作者
將輸出獨(dú)立出來,
用數(shù)組做參數(shù), 一個(gè)線程處理一個(gè)數(shù)組元素。

論壇徽章:
0
9 [報(bào)告]
發(fā)表于 2016-08-19 22:07 |只看該作者
Make sense ! But How ?  please show me something magic ! Trust you ! Thank you so much !!!

論壇徽章:
14
水瓶座
日期:2014-06-10 09:51:0215-16賽季CBA聯(lián)賽之江蘇
日期:2017-11-27 11:42:3515-16賽季CBA聯(lián)賽之八一
日期:2017-04-12 14:26:2815-16賽季CBA聯(lián)賽之吉林
日期:2016-08-20 10:43:1215-16賽季CBA聯(lián)賽之廣夏
日期:2016-06-23 09:53:58程序設(shè)計(jì)版塊每日發(fā)帖之星
日期:2016-02-11 06:20:00程序設(shè)計(jì)版塊每日發(fā)帖之星
日期:2016-02-09 06:20:0015-16賽季CBA聯(lián)賽之上海
日期:2015-12-25 16:40:3515-16賽季CBA聯(lián)賽之廣夏
日期:2015-12-22 09:39:36程序設(shè)計(jì)版塊每日發(fā)帖之星
日期:2015-08-24 06:20:002015亞冠之德黑蘭石油
日期:2015-08-07 09:57:302015年辭舊歲徽章
日期:2015-03-03 16:54:15
10 [報(bào)告]
發(fā)表于 2016-08-20 10:45 |只看該作者
本帖最后由 lxyscls 于 2016-08-20 10:49 編輯

回復(fù) 7# mjus


    https://msdn.microsoft.com/en-us/library/hh750089.aspx
    https://software.intel.com/en-us/node/506077

   多線程,map就沒辦法同步了?就算數(shù)據(jù)很多,但是只要消費(fèi)掉,map還是不會太大。要求輸出順序,當(dāng)然要給輸入編號索引,否則怎么知道出去該誰先誰后
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP