linux网络编程学习笔记之四 -----多线程并发服务端
2014-06-11 20:01
302 查看
相对于使用进程实现并发,用线程的实现更加轻量。每个线程都是独立的逻辑流。线程是CPU上独立调度运行的最小单位,而进程是资源分配的单位。当然这是在微内核的操作系统上说的,简言之这种操作系统的内核是只提供最基本的OS服务,更多参看点击打开链接
每个线程有它自己的线程上下文,包括一个唯一的线程ID(linux上实现为unsigned long),栈,栈指针,程序计数器、通用目的寄存器和条件码,还有自己的信号掩码和优先级。同一个进程里的线程共享这个进程的整个虚拟地址空间,包括可执行的程序文本、程序的全局内存、堆内存、栈和文件描述符。因此,线程的上下文切换比进程迅速得多,但同时也带来了线程之间的同步问题。
几个小Tips:
1、进程ID在整个系统中是唯一的,但线程ID只在它所属的线程环境里有效。
2、每个线程都有errno的副本,不用考虑其同步问题。
3、任意一个线程调用了exit, _Exit, _exit都会造成整个进程的终止。
4、由于描述字的共享性,新创建线程并不影响已打开描述字的引用计数,因此,不要随便close。
线程的几个属性
分离和可结合:如果一个线程能被其他线程收回其资源和杀死,它就是可结合的,否则就是分离的。默认情况下,线程被创建出来是可结合的,这时需要某个原有的线程调用pthread_join()来阻塞等待该进程结束并回收其资源(由于此函数只能等待一个特定线程会导致编码复杂,Steven在UNP中可爱地吐槽了一段,当年与标准设计人员吵了一架)。而分离的线程无需其他线程等待,一旦结束,资源立即被操作系统回收,在其创建是调用pthread_detach()即可实现。
更多的属性如继承性,调度策略,调度 ,作用域和堆栈大小等可以参看APUE12.3
对于属性变量pthread_attr_t可以调用pthread_attr_init设置,但要记得在创建线程后用pthread_attr_destory销毁
进程同步常见方法
1)互斥锁UNP26.7
2)条件变量UNP26.8。需要注意的是pthread_cond_wait()如果没有信号,线程会阻塞直到有信号,但互斥量会立即释放,反之,它返回时,互斥量再次被锁住。
3)信号量CSAPP12.5
上面只是简单地罗列和笔记,线程水太深,我将继续学习。。
惯例,上个简单的服务器端程序:
代码中一些调用函数的实现,移步我的github:https://github.com/simon-xia/lnp
每个线程有它自己的线程上下文,包括一个唯一的线程ID(linux上实现为unsigned long),栈,栈指针,程序计数器、通用目的寄存器和条件码,还有自己的信号掩码和优先级。同一个进程里的线程共享这个进程的整个虚拟地址空间,包括可执行的程序文本、程序的全局内存、堆内存、栈和文件描述符。因此,线程的上下文切换比进程迅速得多,但同时也带来了线程之间的同步问题。
几个小Tips:
1、进程ID在整个系统中是唯一的,但线程ID只在它所属的线程环境里有效。
2、每个线程都有errno的副本,不用考虑其同步问题。
3、任意一个线程调用了exit, _Exit, _exit都会造成整个进程的终止。
4、由于描述字的共享性,新创建线程并不影响已打开描述字的引用计数,因此,不要随便close。
线程的几个属性
分离和可结合:如果一个线程能被其他线程收回其资源和杀死,它就是可结合的,否则就是分离的。默认情况下,线程被创建出来是可结合的,这时需要某个原有的线程调用pthread_join()来阻塞等待该进程结束并回收其资源(由于此函数只能等待一个特定线程会导致编码复杂,Steven在UNP中可爱地吐槽了一段,当年与标准设计人员吵了一架)。而分离的线程无需其他线程等待,一旦结束,资源立即被操作系统回收,在其创建是调用pthread_detach()即可实现。
更多的属性如继承性,调度策略,调度 ,作用域和堆栈大小等可以参看APUE12.3
对于属性变量pthread_attr_t可以调用pthread_attr_init设置,但要记得在创建线程后用pthread_attr_destory销毁
进程同步常见方法
1)互斥锁UNP26.7
2)条件变量UNP26.8。需要注意的是pthread_cond_wait()如果没有信号,线程会阻塞直到有信号,但互斥量会立即释放,反之,它返回时,互斥量再次被锁住。
3)信号量CSAPP12.5
上面只是简单地罗列和笔记,线程水太深,我将继续学习。。
惯例,上个简单的服务器端程序:
#include"simon_socket.h" #define SERV_PORT 12345 typedef struct arg_tag { int connectfd; struct sockaddr_in addr_info; }ARG; void *start_routine(void *arg) { pthread_detach(pthread_self()); process_client(((ARG*)arg) -> connectfd, &((ARG*)arg) -> addr_info); close(((ARG *)arg) -> connectfd); //free(arg); pthread_exit(NULL); } int main() { int sockfd, acfd; size_t sin_len = sizeof(struct sockaddr); ARG *arg; struct sockaddr_in client_addr; pthread_t thread; sockfd = init_tcp_psock(SERV_PORT); while (1) { if ((acfd = accept_request(sockfd, (struct sockaddr *)&client_addr, &sin_len)) <= 0) continue; arg = malloc(sizeof(ARG)); arg -> connectfd = acfd; arg -> addr_info = client_addr; if (pthread_create(&thread, NULL, start_routine, (void*)arg)) { printf("Create thread error!\n"); continue; } free(arg); } close(sockfd); return 0; }
代码中一些调用函数的实现,移步我的github:https://github.com/simon-xia/lnp
相关文章推荐
- linux网络编程学习笔记之三 -----多进程并发服务端
- Java多线程学习笔记—从Map开始说说同步和并发
- 多线程(并发)学习笔记
- java多线程和并发库 学习笔记草稿
- Java学习笔记—多线程(java.util.concurrent并发包概括,转载)
- Java多线程与并发库高级应用 学习笔记 10-16课
- JAVA并发设计模式学习笔记(一)—— JAVA多线程编程
- Java多线程高并发学习笔记——阻塞队列
- JAVA 多线程和并发学习笔记(二)
- Java多线程与并发库高级应用 学习笔记 16-22课 +面试题
- JAVA 多线程和并发学习笔记(四)
- Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition
- Java学习笔记—多线程(并发工具类)
- Java学习笔记—多线程(同步容器和并发容器)
- 黑马程序员学习笔记 Java中多线程与并发的总结
- JAVA 多线程和并发学习笔记(三)
- JAVA 多线程和并发学习笔记(一)
- 学习JAVA多线程编程 --- 《JAVA多线程编程核心技术》第2章 对象及变量的并发访问 笔记
- JAVA高并发学习笔记(二) 多线程基础
- iOS学习笔记-117.多线程16——NSOperationQueue最大并发数