TCP/IP网络编程 多线程服务器端的实现(1)


线程基本概念

前面我们讲过多进程服务器,但我们知道它开销很大,因此我们才引入线程,我们可以把它看成是一种轻量级进程。它相比进程有如下几个优点:

线程的创建和上下文切换开销更小且速度更快。

线程间交换数据时无需特殊技术。

进程:在操作系统构成单独执行流的单位。

线程:在进程构成单独执行流的单位。

它们的包含关系是,操作系统 > 进程 > 线程。进程与线程具体差异其实是这样的,每个进程都有独立的完整内存空间,它包括全局数据区,堆区,栈区,而多进程服务器之所以开销大是因为只是为了区分栈区里的不同函数流执行而把数据区,堆区,栈区内存全部复制了一份。而多线程就高效多了,它只把栈区分离出来,进程中的数据区,堆区则共享。具体内存结构示例图如下:

 TCP/IP网络编程 多线程服务器端的实现

  TCP/IP网络编程 多线程服务器端的实现

线程创建及运行

线程具有单独的执行流,因此需要单独定义线程的入口函数,而且还需要请求操作系统在单独的执行流中执行该函数,完成这个功能的函数如下:

  1. #include 
  2.  
  3. int pthread_create( 
  4.  
  5. pthread_t * restrict thread,//保存线程ID 
  6.  
  7. const pthread_attr_t * restrict attr,//线程属性,NULL默认属性 
  8.  
  9. void * (* start_routine)(void *), //线程入口函数,函数指针 
  10.  
  11. void * restrict arg //传递给入口函数的参数 
  12.  
  13. );

实例代码:

  1. #include 
  2.  
  3. #include 
  4.  
  5. #include 
  6.  
  7. void * thread_main(void *arg); 
  8.  
  9. int main(int argc, char *argv[]) 
  10.  
  11.  
  12. pthread_t t_id; 
  13.  
  14. int thread_param = 5; 
  15.  
  16. if (pthread_create(&t_id, NULL, thread_main, (void *)&thread_param) != 0) 
  17.  
  18.  
  19. puts("pthread_create() error"); 
  20.  
  21. return -1; 
  22.  
  23.  
  24. sleep(10); 
  25.  
  26. puts("end of main"); 
  27.  
  28. return 0; 
  29.  
  30.  
  31. void * thread_main(void *arg) 
  32.  
  33.  
  34. int i; 
  35.  
  36. int cnt =* ((int *)arg); 
  37.  
  38. for (i = 0; i < cnt; i++) 
  39.  
  40.  
  41. sleep(1); 
  42.  
  43. puts("running thread"); 
  44.  
  45.  
  46. return NULL; 
  47.  
  48. }

 TCP/IP网络编程 多线程服务器端的实现

上面实例是用sleep延迟来控制线程的执行的,如果主线程不做延迟那么执行到return 0;时,进程就结束了,相应的线程也会销毁。而明显用sleep这种方式控制线程执行流是不合理的,下面我们来看看一个更好的延迟函数,调用该函数的进程(或线程)将进入等待状态,直到第一个参数为ID的线程终止为止。而且可以得到线程的入口函数返回值。

  1. #include 
  2.  
  3. int pthread_join(pthread_t thread, void **status); 
  4.  
  5. 参数1:线程ID 
  6.  
  7. 参数2:保存线程入口函数的返回值

实例代码:

  1. #include 
  2.  
  3. #include 
  4.  
  5. #include 
  6.  
  7. #include 
  8.  
  9. void * thread_main(void *arg); 
  10.  
  11. int main(int argc, char *argv[]) 
  12.  
  13.  
  14. pthread_t t_id; 
  15.  
  16. int thread_param = 5; 
  17.  
  18. void * thr_ret; 
  19.  
  20. //创建线程 
  21.  
  22. if (pthread_create(&t_id, NULL, thread_main, (void *)&thread_param) != 0) 
  23.  
  24.  
  25. puts("pthread_create() error"); 
  26.  
  27. return -1; 
  28.  
  29.  
  30. //等待线程返回 
  31.  
  32. if (pthread_join(t_id, &thr_ret) != 0) 
  33.  
  34.  
  35. puts("pthread_join() error"); 
  36.  
  37. return -1; 
  38.  
  39.  
  40. printf("Thread return message: %s \n", (char *)thr_ret); 
  41.  
  42. free(thr_ret); 
  43.  
  44. return 0; 
  45.  
  46.  
  47. //线程入口函数 
  48.  
  49. void * thread_main(void *arg) 
  50.  
  51.  
  52. int i; 
  53.  
  54. int cnt =* ((int *)arg); 
  55.  
  56. char * msg = (char *)malloc(sizeof(char) * 50); 
  57.  
  58. strcpy(msg, "Hello, I am thread ~ \n"); 
  59.  
  60. for (i = 0; i < cnt; i++) 
  61.  
  62.  
  63. puts("running thread"); 
  64.  
  65.  
  66. return (void *)msg; 
  67.  
  68. }

TCP/IP网络编程 多线程服务器端的实现




相关内容