本文介绍了三种构建线程解决方案的方式。

一、流水线:每个线程执行同一种操作,并把操作结果传递给下一步骤的线程。

代码示例如下:
终端输入一个int值,每个线程将该值加1,并将结果传给下一个线程。

  1. #include<stdio.h>
  2. #include<pthread.h>
  3. typedef struct stage_tag
  4. {
  5. pthread_mutex_t mutex;
  6. pthread_cond_t cond;
  7. int data;
  8. int ready;
  9. pthread_t tid;
  10. struct stage_tag *next;
  11. }stage_t;
  12. typedef struct pipe_tag
  13. {
  14. pthread_mutex_t mutex;
  15. stage_t *head;
  16. stage_t *tail;
  17. int stages;
  18. }pipe_t;
  19. void pipe_send(stage_t *stage,int data)
  20. {
  21. stage->data =data;
  22. stage->ready = ;
  23. pthread_cond_signal(&stage->cond);
  24. }
  25. void *thread_route(void *arg)
  26. {
  27. stage_t *stage = (stage_t *)arg;
  28. while(!stage->ready)
  29. {
  30. pthread_cond_wait(&stage->cond,&stage->mutex);
  31. }
  32. int data = stage->data+;
  33. stage_t *next = stage->next;
  34. if(next!=NULL)
  35. {
  36. pipe_send(next,data);
  37. }
  38. return NULL;
  39. }
  40. void create_pipe(pipe_t *pipe,int stages)
  41. {
  42. // pipe = (pipe_t *)malloc(sizeof(pipe_t));
  43. pipe->stages = stages;
  44. int i;
  45. stage_t *stage;
  46. stage_t *last;
  47. for(i=;i<=stages;i++)
  48. {
  49. stage = (stage_t *)malloc(sizeof(stage_t));
  50. stage->data = i;
  51. if(i==)
  52. {
  53. pipe->head = stage;
  54. }
  55. if(last!=NULL)
  56. {
  57. last->next = stage;
  58. }
  59. last = stage;
  60. }
  61. last->next=NULL;
  62. pipe->tail = last;
  63. for(stage=pipe->head;stage->next!=NULL;stage=stage->next)
  64. {
  65. pthread_create(&stage->tid,NULL,thread_route,(void *)stage);
  66. printf("stage %d\n",stage->data);
  67. }
  68. /* free(pipe);
  69. for(stage=pipe->head;stage!=NULL;stage=stage->next)
  70. {
  71. free(stage);
  72. }
  73. */
  74. }
  75. int main(void)
  76. {
  77. pipe_t my_pipe;
  78. long value,result;
  79. char line[];
  80. create_pipe(&my_pipe,);
  81. pipe_send(my_pipe.head,);
  82. sleep();
  83. printf("result is %d\n",my_pipe.tail->data);
  84. return ;
  85. }

二、工作组:数据由一组线程分别独立地处理。

代码示例如下:
程序有两个参数:filepath:文件或目录路径;search:待查找字符串

程序将文件路径排队给工作组,工作组线程判断该路径是文件还是目录,如果是文件,它将在文件中搜索字符串;如果是目录,它将使用readdir_r查找该目录中的所有子目录和文件,并将每一项添加到工作队列。

  1. #include<stdio.h>
  2. #include<pthread.h>
  3. #include<dirent.h>
  4. #include<sys/stat.h>
  5. typedef struct work_tag
  6. {
  7. struct work_tag *next;
  8. char *path;
  9. char *search;
  10. }work_t,*work_p;
  11. typedef struct worker_tag
  12. {
  13. int index;
  14. pthread_t tid;
  15. struct crew_tag *crew;
  16.  
  17. }worker_t,*worker_p;
  18. typedef struct crew_tag
  19. {
  20. pthread_mutex_t mutex;
  21. pthread_cond_t cond;
  22. pthread_cond_t done;
  23. long work_count;
  24. work_t *first,*last;
  25. worker_t workers[];
  26. }crew_t,*crew_p;
  27. void *thread_route(void *arg)
  28. {
  29. worker_p worker = (worker_t *)arg;
  30. crew_p crew = worker->crew;
  31. struct dirent *entry;
  32. entry = (struct dirent*)malloc(sizeof(struct dirent)+sizeof(size_t));
  33. pthread_mutex_lock(&crew->mutex);
  34. while(crew->work_count ==)
  35. {
  36. pthread_cond_wait(&crew->cond,&crew->mutex);
  37. }
  38. pthread_mutex_unlock(&crew->mutex);
  39. printf("worker is running: %d\n",worker->index);
  40. while()
  41. {
  42. pthread_mutex_lock(&crew->mutex);
  43. while(crew->first==NULL)
  44. {
  45. pthread_cond_wait(&crew->cond,&crew->mutex);
  46. }
  47. printf("worker %d woke %#lx %d\n",worker->index,crew->first,crew->work_count);
  48. work_p work = crew->first;
  49. crew->first = work->next;
  50. if(crew->first==NULL)
  51. crew->last = NULL;
  52. printf("worker %d took %#lx,leave first %#lx,last %#lx\n",worker->index,work,crew->first,crew->last);
  53. pthread_mutex_unlock(&crew->mutex);
  54. struct stat filestat;
  55. lstat(work->path,&filestat);
  56. if(S_ISLNK(filestat.st_mode))
  57. printf("worker %d:%s is a link,skipping.\n",worker->index,work->path);
  58. else if(S_ISDIR(filestat.st_mode)){
  59. DIR *dir;
  60. struct dirent *result;
  61. dir = opendir(work->path);
  62. while(){
  63. readdir_r(dir,entry,&result);
  64. if(result==NULL)
  65. break;
  66. if(strcmp(entry->d_name,".")==)
  67. continue;
  68. if(strcmp(entry->d_name,"..")==)
  69.  
  70. continue;
  71. work_p new_work = (work_p)malloc(sizeof(work_t));
  72. printf("test\n");
  73. path_max = pathconf (work->path, _PC_PATH_MAX);
  74. new_work->path = (char*)malloc (path_max);
  75. strcpy (new_work->path, work->path);
  76. strcat (new_work->path, "/");
  77. strcat (new_work->path, entry->d_name);
  78. // char *new_dir = strcat(work->path,entry->d_name);
  79. //new_work->path = new_dir;
  80. new_work->search = work->search;
  81. new_work->next = NULL;
  82. pthread_mutex_lock(&crew->mutex);
  83. if(crew->first==NULL)
  84. {
  85. crew->first = new_work;
  86. crew->last = new_work;
  87. }
  88. else{
  89. crew->last->next = new_work;
  90. crew->last = new_work;
  91. }
  92. crew->work_count++;
  93. printf("worker %d add work %#lx,first %#lx,last %#lx,%d\n",worker->index,new_work,crew->first,crew->last,crew->work_count);
  94. pthread_cond_signal(&crew->cond);
  95. pthread_mutex_unlock(&crew->mutex);
  96. }
  97. closedir(dir);
  98. }
  99. else if(S_ISREG(filestat.st_mode)){
  100. FILE *file;
  101. char buffer[];
  102. file = fopen(work->path,"r");
  103. fgets(buffer,sizeof(buffer),file);
  104. char *search_ptr;
  105. search_ptr = strstr(buffer,work->search);
  106. if(search_ptr!=NULL){
  107. printf("worker %d found \"%s\" in %s\n ",worker->index,work->search,work->path);
  108. }
  109. fclose(file);
  110.  
  111. }
  112. else{
  113. printf("worker %d:%s format is error.\n",worker->index,work->path);
  114. }
  115. free(work->path);
  116. free(work);
  117.  
  118. pthread_mutex_lock(&crew->mutex);
  119. crew->work_count--;
  120. printf("worker %d decremented work to %d\n",worker->index,crew->work_count);
  121. if(crew->work_count<=){
  122. pthread_cond_broadcast(&crew->done);
  123. }
  124. pthread_mutex_unlock(&crew->mutex);
  125. }
  126. free(entry);
  127. return NULL;
  128. }
  129. void crew_create(crew_t *crew)
  130. {
  131. int worker_index;
  132. crew->work_count = ;
  133. crew->first = NULL;
  134. crew->last = NULL;
  135. pthread_mutex_init(&crew->mutex,NULL);
  136. pthread_cond_init(&crew->cond,NULL);
  137. pthread_cond_init(&crew->done,NULL);
  138. for(worker_index=;worker_index<;worker_index++){
  139. crew->workers[worker_index].index = worker_index;
  140. crew->workers[worker_index].crew = crew;
  141. pthread_create(&crew->workers[worker_index].tid,
  142. NULL,thread_route,(void *)&crew->workers[worker_index]);
  143. }
  144. }
  145. void crew_start(crew_t *crew,char *filepath,char *search)
  146. {
  147. pthread_mutex_lock(&crew->mutex);
  148. work_p work = (work_p)malloc(sizeof(work_t));
  149. work->path = filepath;
  150. work->search = search;
  151. work->next = NULL;
  152. crew->first = work;
  153. crew->last = work;
  154. crew->work_count++;
  155. pthread_cond_signal(&crew->cond);
  156. while(crew->work_count>)
  157. {
  158. pthread_cond_wait(&crew->done,&crew->mutex);
  159. }
  160. printf("crew is done!\n");
  161. pthread_mutex_unlock(&crew->mutex);
  162. }
  163. int main(void)
  164. {
  165. crew_t crew;
  166. crew_create(&crew);
  167. char *filepath = "/home/ubuntu/programs";
  168. char *search = "errno";
  169. crew_start(&crew,filepath,search);
  170. return ;
  171. }

三、客户端/服务器:客户端线程将工作排队,交给一个服务器线程去处理。客户端或者以同步方式等待服务器执行,或异步执行并在后面需要时查找结果。

代码示例如下:
一组线程都需要从stdin中读取输入,这将导致提示-读(prompt-and-read)操作可能有些混乱。一个方法是使用flockfile和funlockfile函数来锁住stdin和stdout。,另一个方式是,使用服务器线程,将客户端读写操作排队,由服务器线程依次处理读写操作队列。

  1. #include<stdio.h>
  2. #include<pthread.h>
  3. #define REQ_READ 1
  4. #define REQ_WRITE 2
  5. #define REQ_QUIT 3
  6. typedef struct client_tag
  7. {
  8. struct client_tag *next;
  9. int oper;
  10. int sync;
  11. int done_flag;
  12. char prompt[];
  13. char text[];
  14. pthread_mutex_t mutex;
  15. pthread_cond_t mutex;
  16. }client_t;
  17. typedef struct server_tag
  18. {
  19. client_t *first,*last;
  20. pthread_mutex_t mutex;
  21. pthread_cond_t cond;
  22. }server_t;
  23. server_t server={NULL,NULL,PTHREAD_MUTEX_INITIALIZER,PTHREAD_COND_INITIALIZER};
  24. pthread_mutex_t main_mutex = PTHREAD_MUTEX_INITIALIZER;
  25. pthread_cond_t main_cond = PTHREAD_COND_INITIALIZER;
  26. int thread_count = ;
  27. void client_request(int oper,int sync,const char *prompt,char *string)
  28. {
  29. pthread_mutex_lock(&server.mutex);
  30. client_t *client;
  31. client = (client_t *)malloc(sizeof(client_t));
  32. client->next = NULL;
  33. client->oper = oper;
  34. client->sync = sync;
  35. if(prompt!=NULL)
  36. strncpy(client->prompt,prompt,);
  37. if(oper==REQ_WRITE&&string!=NULL)
  38. strncpy(client->text,string,);
  39. if(server.first==NULL)
  40. {
  41. server.first = client;
  42. server.last = client;
  43. }else{
  44. server.last->next = client;
  45. server.last = client;
  46. }
  47. pthread_cond_signal(&server.cond);
  48. if(sync)
  49. {
  50. while(!client->done_flag)
  51. {
  52. pthread_cond_wait(&client->cond,&server.mutex);
  53. }
  54. if(oper==REQ_READ)
  55. {
  56. if(strlen(client->text)>)
  57. strcpy(string,client->text);
  58. }
  59. }
  60. pthread_cond_destroy(&client->cond);
  61. free(request);
  62. }
  63. pthread_mutex_unlock(&server.mutex);
  64. }
  65. void *client_route(void *arg)
  66. {
  67. int index = (int)arg;
  68. int loops;
  69. char prompt[];
  70. char string[],formatted[];
  71. sprintf(prompt,"Client %d>",index);
  72. while()
  73. {
  74. client_request(REQ_READ,,prompt,string);
  75. if(strlen(string)==)
  76. break;
  77. for(loops=;loops<;loops++)
  78. {
  79. sprintf(formatted,"(%d#%d) %s",index,loops,string);
  80. client_request(REQ_WRITE,,NULL,formatted);
  81. sleep();
  82. }
  83. }
  84. }
  85. void *server_route(void *arg)
  86. {
  87. client_t *client;
  88. int oper;
  89. while()
  90. {
  91. pthread_mutex_lock(&server.mutex);
  92. while(server.first==NULL)
  93. {
  94. pthread_cond_wait(&server.cond,&server.mutex);
  95. }
  96. client = server.first;
  97. server.first = client.next;
  98. if(server.first==NULL)
  99. server.last = NULL;
  100. pthread_mutex_unlock(&server.mutex);
  101. oper = client->oper;
  102. switch(oper){
  103. case REQ_QUIT:
  104. break;
  105. case REQ_READ:
  106. if(strlen(client->prompt)>)
  107. printf(client->prompt);
  108. fgets(client->text,,stdin);
  109. break;
  110. case REQ_WRITE:
  111. puts(client->text);
  112. break;
  113. default:
  114. break;
  115. }
  116. free(client);
  117. if(oper==REQ_QUIT)
  118. break;
  119. }
  120. return NULL;
  121. }
  122. int main(void)
  123. {
  124. pthread_t sid;
  125. pthread_create(&sid,NULL,server_route,NULL);
  126.  
  127. pthread_t cid;
  128. int i;
  129. for(i=;i<thread_count;i++)
  130. {
  131. pthread_create(&cid,NULL,client_route,(void *)count);
  132. }
  133. pthread_mutex_lock(&main_mutex);
  134. while(thread_count>)
  135. {
  136. pthread_cond_wait(&main_cond,&main_mutex);
  137. }
  138. pthread_mutex_unlock(&main_mutex);
  139. printf("Done!\n");
  140. client_request(REQ_QUIT,,NULL,NULL);
  141. return ;
  142. }

参考资料:《POSIX多线程程序设计》 pp.81-110

posix多线程--三种基本线程编程模型的更多相关文章

  1. 多线程(三) java中线程的简单使用

    java中,启动线程通常是通过Thread或其子类通过调用start()方法启动. 常见使用线程有两种:实现Runnable接口和继承Thread.而继承Thread亦或使用TimerTask其底层依 ...

  2. 【Java 线程的深入研究1】Java 提供了三种创建线程的方法

    Java 提供了三种创建线程的方法: 通过实现 Runnable 接口: 通过继承 Thread 类本身: 通过 Callable 和 Future 创建线程. 1.通过实现 Runnable 接口来 ...

  3. JAVA基础知识之多线程——三种实现多线程的方法及区别

    所有JAVA线程都必须是Thread或其子类的实例. 继承Thread类创建线程 步骤如下, 定义Thead子类并实现run()方法,run()是线程执行体 创建此子类实例对象,即创建了线程对象 调用 ...

  4. Android 中三种启用线程的方法

    在多线程编程这块,我们经常要使用Handler(处理),Thread(线程)和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢? 首先说明Android的CPU分配的最小单元是线程,Han ...

  5. Java 多线程 三种实现方式

    Java多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没 ...

  6. JAVA多线程三种实现方式

    JAVA多线程实现方式主要有三种:继承Thread类.实现Runnable接口.使用ExecutorService.Callable.Future实现有返回结果的多线程.其中前两种方式线程执行完后都没 ...

  7. java线程(1)——三种创建线程的方式

    前言 线程,英文Thread.在java中,创建线程的方式有三种: 1.Thread 2.Runnable 3.Callable 在详细介绍下这几种方式之前,我们先来看下Thread类和Runnabl ...

  8. java线程——三种创建线程的方式

    前言 线程,英文Thread.在java中,创建线程的方式有三种: 1.Thread 2.Runnable 3.Callable 在详细介绍下这几种方式之前,我们先来看下Thread类和Runnabl ...

  9. 三种Shell脚本编程中避免SFTP输入密码的方法

    最近编程中用到sftp上传文件,且需要用crontab预设定时上传事件.而sftp不同于ftp,没有提供选项如 -i 可以将密码直接编码进程序.使用sftp指令,会自动请求用户输入密码. 总结一下可以 ...

随机推荐

  1. eclipse使用egit插件

    本来想用myeclipse,奈何试过网上所列的常用方法,都无法成功安装egit插件.只得转到eclipse.话说eclipse不仅是免费的,启动也较myeclipse更为迅速,安装插件也非常顺利.使用 ...

  2. git工具 将源码clone到本地指定目录的三种方式

      git工具 将源码clone到本地指定目录的三种方式 CreationTime--2018年7月27日15点34分 Author:Marydon 1.情景展示 运行git-bash.exe,输入命 ...

  3. 〖Linux〗Ubuntu13.10中使用虚拟机对MTK手机进行线刷

    最近一个同学把一台MTK手机刷坏了,在我的笔记本电脑上没有WindowsXp操作系统: 而在MTK线刷过程中,最好的刷机系统便是WindowsXP3,于是有了想在Linux中直接开启XP虚拟机来刷机的 ...

  4. java 中文转拼音之pinyin4j

    一.简介 有时候,须要将汉字编程相应的拼音.以方便数据的处理.比方在Android手机应用的开发上.要查询联系人的姓名.通常都是用拼音进行查询的. 比方要查询"曹孟德",就能够输入 ...

  5. CentOS 6.4 配置DNS

    vi /etc/resolv.conf 写入以下内容并保存: nameserver x.x.x.x 重启服务以生效: service network restart

  6. 【TP3.2】跨库操作和跨域操作

    一.跨库操作:(同一服务器,不同的数据库) 假设UserModel对应的数据表在数据库user下面,而InfoModel对应的数据表在数据库info下面,那么我们只需要进行下面的设置即可. class ...

  7. springmvc异常统一处理

    http://www.cnblogs.com/xd502djj/archive/2012/09/24/2700490.html

  8. 求不小于N且二进制串包含K个1的最小的数字

    给定正整数N,求一个最小正整数M(M>=N),使得M中连续1的个数不小于K. 输入格式:N K 其中N为大整数,只能进行字符串处理 首先要把N化为二进制串,考察这个二进制串的最后K位: 直接把这 ...

  9. javascript高级程序设计第三章

    看后总结: 1.区分大小写 2.标识符是有字母下划线$开头,并有字母.下划线.数字.美元符号组成. 3.建议用驼峰法命名标识符. 4.注释: 单行:// 多行: /*   */ 5.严格模式: 在js ...

  10. Windows 7下在DebugView中显示调试信息

    自Windows Vista以来,调试信息在默认状态下是不显示的.为了显示调试信息,按照如下步骤设置即可: 1. 打开注册表: 2. 在HKLM\SYSTEM\CuurentControlSet\Co ...