免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: baohuaihuai
打印 上一主题 下一主题

新鲜出炉Google面试题一道(多线程) [复制链接]

论坛徽章:
0
91 [报告]
发表于 2011-06-03 19:19 |只看该作者

  1. #include <unistd.h>
  2. #include <stdio.h>
  3. #include <pthread.h>
  4. #include <string.h>
  5. #include <errno.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <fcntl.h>
  9. #include <stdlib.h>

  10. #define THREAD_NUM        (4)
  11. #define        FILE_NUM        THREAD_NUM

  12. struct _thread_pipe
  13. {
  14.         int        w_pipe;
  15.         int r_pipe;
  16. //        int file_fd;
  17. }thread_pipe[THREAD_NUM];

  18. struct _thread_data
  19. {
  20.         pthread_t        thid;
  21.         int                        *filefds;
  22.         void                 *data;
  23.         int                        seq;
  24. };

  25. char *file_name[] = {"./A", "./B", "./C", "./D"};

  26. void *thread_write(void *param)
  27. {
  28.         struct _thread_data *thdata = (struct _thread_data *)param;
  29.         int                                        i = 0;
  30.         char                                c = 0;
  31.        
  32.         for (i = 0; i <= thdata->seq; ++i)
  33.         {
  34.                 int                nlen = strlen((char *)thdata->data);
  35.                 if (write(thdata->filefds[i], (char *)thdata->data, nlen) != nlen)
  36.                 {
  37.                         fprintf(stderr, "write error: %s\n", strerror(errno) );
  38.                         pthread_exit( (void *)-1);
  39.                 }
  40.         }
  41.        
  42.         if (thdata->seq == (FILE_NUM-1) )  /* last thread write complete */
  43.         {
  44.                 c = 1;
  45.                 write(thread_pipe[THREAD_NUM-1].w_pipe, &c, 1);
  46.         }
  47.        
  48.         while (1)
  49.         {
  50.                 read(thread_pipe[thdata->seq].r_pipe, &c, 1);
  51.                
  52.                 for (i = 0; i < FILE_NUM; ++i)
  53.                 {
  54.                         size_t        nlen = strlen(thdata->data);
  55.                         write(thdata->filefds[i], thdata->data, nlen);
  56.                 }
  57.                
  58.                 c = ( ( (c+1)%4)? (c+1) : 1);
  59.                 write(thread_pipe[thdata->seq].w_pipe, &c, 1);
  60.         }
  61.        
  62.         pthread_exit(0);
  63. }

  64. int main(void)
  65. {
  66.         int                i = 0;
  67.         int                pipe_fds[THREAD_NUM][2];
  68.         struct _thread_data        thread_data[THREAD_NUM];
  69.         char        *wdata[] = {"1", "2", "3", "4"};
  70.         int                fds[FILE_NUM];
  71.        
  72.         /* create pipe */
  73.         for (i = 0; i < THREAD_NUM; ++i)
  74.         {
  75.                 if (pipe(pipe_fds[i]) < 0)
  76.                 {
  77.                         fprintf(stderr, "pipe error: %s\n", strerror(errno));
  78.                         exit(-1);
  79.                 }
  80.         }
  81.        
  82.         for (i = 0; i < THREAD_NUM; ++i)
  83.         {
  84.                 thread_pipe[i].w_pipe = pipe_fds[i][1];
  85.                 thread_pipe[(i+1)%THREAD_NUM].r_pipe = pipe_fds[i][0];
  86.         }
  87.        
  88.         for (i = 0; i < FILE_NUM; ++i)
  89.         {
  90.                 if ( (fds[i] = open(file_name[i], O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU)) < 0)
  91.                 {
  92.                         fprintf(stderr, "open error: %s\n", strerror(errno));
  93.                         exit(-1);
  94.                 }
  95.         }
  96.        
  97.         for (i = 0; i < THREAD_NUM; ++i)
  98.         {
  99.                 thread_data[i].data = wdata[i];
  100.                 thread_data[i].seq = i;
  101.                 thread_data[i].filefds = fds;
  102.                 pthread_create(&(thread_data[i].thid), NULL, thread_write, &thread_data[i]);
  103.         }
  104.        
  105.         /* wait for thread to terminate */
  106.         for (i = 0; i < THREAD_NUM; ++i)
  107.         {
  108.                 pthread_join(thread_data[i].thid, NULL);
  109.         }
  110.        
  111.         /* close all opened files or devices */
  112.        
  113.         return 0;
  114. }

复制代码

论坛徽章:
0
92 [报告]
发表于 2011-06-03 21:39 |只看该作者
这道题如果用锁去做的话,还要保证锁的顺序,效率就更加不用说了。

为什么不想到用一个buf,四个线程只管输出自己的数值到buf的相应段位置,主线程不停从buf取值输出到文件呢?

论坛徽章:
154
2022北京冬奥会纪念版徽章
日期:2015-08-07 17:10:5720周年集字徽章-年
日期:2022-10-26 16:44:2015-16赛季CBA联赛之深圳
日期:2022-11-02 14:02:4515-16赛季CBA联赛之八一
日期:2022-11-28 12:07:4820周年集字徽章-20	
日期:2023-07-19 08:49:4515-16赛季CBA联赛之八一
日期:2023-11-04 19:23:5115-16赛季CBA联赛之广夏
日期:2023-12-13 18:09:34
93 [报告]
发表于 2011-06-04 01:20 |只看该作者
看一下,没懂

看来水平还不够

论坛徽章:
0
94 [报告]
发表于 2011-06-04 02:57 |只看该作者
回复 92# 独臂剑客
如何保证4个线程向buf输出的顺序呢,这是个问题吧?

论坛徽章:
0
95 [报告]
发表于 2011-06-04 08:28 |只看该作者
回复 94# 麦哥哥


    一块buf的话,不同线程处于buf不同位置段,或者4块buf都行,随便写个环形buf都OK.

论坛徽章:
0
96 [报告]
发表于 2011-06-04 14:48 |只看该作者
我是个多线程新手,不过我跟92楼的想法一样,用4个BUFF,没个线程往固定的位置写,这是一个固定的循环嘛!这样不用用到锁也是对的,主线程可以设置一个定时器,每过一秒刷下缓存,这个时候需要加锁了,如果定时器太麻烦的话也可以在4个线程中间设置一个计数器啊!写多少次的适合就刷新一下,同样需要加锁!

求职 : c/c++研发
论坛徽章:
0
97 [报告]
发表于 2011-06-05 01:30 |只看该作者
看完题目后,第一个念头就是利用条件锁,于是就写了个试试!新手,多批评!
大体的思路是:每个文件都有一个条件锁,4个线程对每个文件取锁,当取到锁时,查看是不是该此线程写,如果不是的话就解锁,查看下一个文件;如果是的话就写内容到此文件,然后将findex的值赋成下一个该写的线程的值
  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <string.h>
  4. #include <unistd.h>

  5. #define NUM 4
  6. #define FILE_NAME_LEN 8
  7. typedef struct LockStruct
  8. {
  9.         pthread_mutex_t lock;
  10.         int findex;
  11. }LockStruct;

  12. typedef struct MyStruct
  13. {
  14.         FILE *fp[NUM];
  15.         LockStruct flock[NUM];
  16. }MyStruct;

  17. MyStruct g_par;
  18. void* ThreadHandle(void*);

  19. int main(int argc, char** argv)
  20. {
  21.         int i;

  22. /*
  23.         init g_par
  24. */
  25.         for(i = 0; i < NUM; i++)
  26.         {
  27.                 phtread_mutex_init(&g_par.flock[i].lock);
  28.                 g_par.flock[i].findex = i;
  29.         }

  30. /*
  31.         Open File
  32. */
  33.         const char filename[NUM][FILE_NAME_LEN] = {"A", "B", "C", "D"};
  34.         for(i = 0; i < NUM; i++)
  35.         {
  36.                 g_par.fp[i] = fopen(filename[i], "w+");
  37.                 if(g_par.fp[i] == NULL)
  38.                 {
  39.                         printf("Open file %s failed!\n", filename[i]);
  40.                         exit(-1);
  41.                 }
  42.         }

  43. /*
  44.         create thread
  45. */
  46.         int ret;
  47.         pthread_t pid[NUM];
  48.         for(i = 0; i < NUM; i++)
  49.         {
  50.                 ret = pthread_create(&pid[i], NULL, ThreadHandle, (void*)&i);
  51.                 if(ret != 0)
  52.                 {
  53.                         printf("create %d thread failed! ret = %d\n", i, ret);
  54.                         exit(-1);
  55.                 }
  56.         }

  57. /*
  58.         sleep
  59. */
  60.         while(1)
  61.         {
  62.                 sleep(1);
  63.         }
  64.         return 0;
  65. }


  66. void* ThreadHandle(void* arg)
  67. {
  68.         int index = *(int*)arg;
  69.         int i;
  70.         while(1)
  71.         {
  72.                 for(i = 0 ; i < NUM; i++)//对4个文件循环查看
  73.                 {
  74. /* 取锁*/
  75.                         pthread_mutex_lock(&g_par.flock[i].lock);       
  76.                         if(g_par.flock[i].findex == index) //是不是该本线程写
  77.                         {
  78.                                 fprintf(g_par.fp[i], "%d", index+1);//是轮到本线程,写内容
  79.                                 fflush(g_par.fp[i]);
  80.                                 g_par.flock[i].findex == 3 ? g_par.flock[i].findex = 0 : g_par.flock[i].findex++; //将findex的值改成下个线程的值
  81.                         }
  82.                         pthread_mutex_unlock(&g_par.flock[i].lock);       
  83.                 }
  84.         }
  85. }
复制代码

论坛徽章:
0
98 [报告]
发表于 2011-06-06 17:54 |只看该作者
本帖最后由 麦哥哥 于 2011-06-06 18:00 编辑
回复  麦哥哥


    一块buf的话,不同线程处于buf不同位置段,或者4块buf都行,随便写个环形buf都OK.
独臂剑客 发表于 2011-06-04 08:28

恩。不失为一个更高效率的做法,可以减少锁的使用,而且减少了写文件次数,系统调用少了,效率提高不少。
PS:你Tencent的么?招人?

论坛徽章:
0
99 [报告]
发表于 2011-06-06 18:38 |只看该作者
回复 98# 麦哥哥


    TX的,现在急招QQ后台开发职位,具体参见:
    http://bbs.chinaunix.net/thread-2327967-1-1.html
   
    麦哥哥及各位cuer,最近有换工作打算的或者各位cuer有朋友、同事等要换工作的,麻烦帮推荐 一下,多谢!

   email到:vultureli@qq.com;wangshuai@vip.qq.com;randy@vip.qq.com;

    如果有想换工作的同学可以站内短信联系我,有相关问题可以站内信息,收到必定回复。

    有想换工作的同学Email啊或有相关同事,朋友想换工作的帮忙推荐 一下, 多谢!

论坛徽章:
0
100 [报告]
发表于 2011-06-07 17:04 |只看该作者
工作线程围绕文件状态处理,发一个无视CPU的实现,5秒生成的A,B,C,D每个文件均为4M左右。
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <sys/stat.h>
  6. #include <sys/types.h>
  7. #include <pthread.h>
  8. #include <signal.h>

  9. #define WORKER_COUNT (4)

  10. class file_writer
  11. {
  12. public:

  13.     int init(int worker_id)
  14.     {
  15.         snprintf(m_filename,sizeof(m_filename),"%c",'A' + worker_id) ;
  16.         m_fd = open(m_filename,O_WRONLY|O_CREAT);
  17.         if(m_fd < 0 ) return -1 ;
  18.         m_worker_id = worker_id ;
  19.         m_buf_pos = 0  ;
  20.     }

  21.     void fini()
  22.     {
  23.         if(m_fd >0)
  24.         {
  25.             ::write(m_fd,m_buf_data,m_buf_pos) ;
  26.             close(m_fd) ;
  27.             m_fd = -1 ;
  28.         }

  29.     }

  30.     int write( int worker_id)
  31.     {
  32.         char v = '1' + (char)worker_id ;
  33.         m_buf_data[m_buf_pos++] = v ;
  34.         if(m_buf_pos == sizeof(m_buf_data) )
  35.         {
  36.             ::write(m_fd,m_buf_data,m_buf_pos) ;
  37.             m_buf_pos = 0 ;
  38.         }
  39.         
  40.         m_worker_id = (m_worker_id+1)%WORKER_COUNT ;

  41.     }

  42.     int get_worker_id()
  43.     {
  44.         return m_worker_id ;
  45.     }
  46.    

  47.     file_writer():m_fd(-1) { } ;
  48.     ~file_writer() { fini() ; } ;

  49. private:
  50.     char m_filename[64] ;
  51.     int m_fd ;
  52.     int m_worker_id ;
  53.     char m_buf_data[4096] ;
  54.     int m_buf_pos ;

  55. } ;

  56. typedef struct
  57. {
  58.     pthread_t tid ;
  59.     int worker_id ;

  60. } worker_info ;


  61. static file_writer writers[WORKER_COUNT] ;

  62. static volatile int running = 1 ;

  63. void* worker_func(void* args)
  64. {
  65.     worker_info *worker = (worker_info*)args ;
  66.     printf("worker %d started , tid:%ld\n",worker->worker_id,worker->tid);
  67.     while(running)
  68.     {
  69.         file_writer *writer = NULL ;
  70.         for(int i = 0 ; i < WORKER_COUNT ; ++i)
  71.         {
  72.             writer = writers + i ;
  73.             if(writer->get_worker_id() == worker->worker_id )
  74.             {
  75.                 writer->write( worker->worker_id) ;
  76.             }
  77.         }

  78.     }
  79.     printf("worker %d stopped , tid:%ld\n",worker->worker_id,worker->tid);
  80.     return NULL ;
  81. }

  82. int main(int argc,char** argv)
  83. {
  84.    
  85.     worker_info workers[WORKER_COUNT] = {0} ;
  86.     for(int i=0;i<WORKER_COUNT;++i)
  87.     {
  88.         writers[i].init(i) ;
  89.         workers[i].worker_id = i ;
  90.         pthread_create(&workers[i].tid,NULL,worker_func,workers+i) ;

  91.     }
  92.    
  93.     sleep(5) ;
  94.     running = 0 ;
  95.     for(int i=0;i<WORKER_COUNT;++i)
  96.     {
  97.         pthread_join( workers[i].tid,NULL) ;
  98.     }

  99.     return 0 ;
  100. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP