29、深入理解计算机系统笔记,并发编程(concurrent)(1)
1、如果逻辑控制流在时间上重叠,那么它们就是并发的。这种现象,称为并发(concurrency)。
2、为了允许服务器同时为大量客户端服务,比较好的方法是:创建并发服务器,为每个客户端创建各自独立的逻辑流。现代OS提供的常用构造并发的方法有:
进程和线程。
1)每个逻辑流都是一个进程,由内核来调度维护。每个进程都有独立的虚拟地址空间,控制流通过IPC机制来进行通信。
2)线程:运行在单一进程上下文中的逻辑流,由内核进行调度,共享同一进程的虚拟地址空间。
由于进程控制和IPC的开销较高,所以基于进程的设计比基于线程的设计慢。
常见IPC有:管道,FIFO,共享存储器,信号。
3、基于线程的并发编程
线程由内核自动调度,每个线程都有它自己的线程上下文(thread context),包括一个惟一的整数线程ID(Thread ID,TID),栈,栈指针,程序计数器,通用目的寄存器和条件码。每个线程和其他线程一起共享进程上下文的剩余部分,包括整个用户的虚拟地址空间,它是由只读文本(代码),读/写数据,堆以及所有的共享库代码和数据区域组成的,还有,线程也共享同样的打开文件的集合。
1)线程执行模型
线程不像进程那样,不是按照严格的父子层次来组织的。和一个进程相关的线程组成一个对等线程池(a pool of peers),独立于其他线程创建的线程(The threads associated with a process form a pool of peers, independent of which threads were created by which other threads.个人理解,这句是说独立于其他进程的线程池中的线程)。进程中第一个运行的线程称为主线程。对等(线程)池概念的主要影响是,一个线程可以杀死它的任何对等线程,或者等待它的任意对等线程终止;进一步来说,每个对等线程都能读写相同的共享数据。
2)关于posix线程示例,及其相关函数,参见原书13.3.2节中。这部分举的例子很经典,值得一读
3)分离线程
在任何一个时间点上,线程是可结合的(joinable),或者是分离的(detached)。一个可结合的线程能够被其他线程收回其资源和杀死。在被其他线程回收之前,它的存储器资源(如栈)是不释放的。相反,一个分离的线程是不能被其他线程回收或杀死的,它的存储器资源在它终止时由系统自动释放。
示例程序
/* * echoservert.c - A concurrent echo server using threads */ /* $begin echoservertmain */ #include "csapp.h" void echo( int connfd); void * thread ( void *vargp); int main( int argc, char **argv) { int listenfd, *connfdp, port, clientlen= sizeof ( struct sockaddr_in); struct sockaddr_in clientaddr; pthread_t tid; if (argc != 2) { fprintf (stderr, "usage: %s <port>\n" , argv[0]); exit (0); } port = atoi (argv[1]); listenfd = Open_listenfd(port); while (1) { connfdp = Malloc( sizeof ( int )); *connfdp = Accept(listenfd, (SA *) &clientaddr, &clientlen); Pthread_create(&tid, NULL, thread , connfdp); } } /* thread routine */ void * thread ( void *vargp) { int connfd = *(( int *)vargp); Pthread_detach(pthread_self()); Free(vargp); echo(connfd); Close(connfd); return NULL; } /* $end echoservertmain */ |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)