進程和線程的區別:
詳細的可以參考這樣文檔進程和線程的區別(超詳細)-CSDN博客? ? ? ? ? ? ? ?
核心比喻
-
進程 = 一個工廠:這個工廠擁有獨立的資源(廠房、原材料、資金、電力)。每個工廠之間是相互隔離的,一個工廠著火不會直接影響另一個工廠。
-
線程 = 工廠里的工人:多個工人在一個工廠里協同工作,他們共享工廠的所有資源(廠房、原材料)。工人們可以獨立地執行不同的任務(流水線),但他們需要溝通和協調,因為他們在共用同一個空間的資源。
詳細區別對比表
維度 | 進程 (Process) | 線程 (Thread) |
---|---|---|
基本定義 | 資源分配的基本單位。一個正在執行的程序實例。 | CPU調度和執行的基本單位。是進程內部的一個執行流。 |
資源擁有 | 擁有獨立的系統資源(如內存、I/O設備、文件等)。每個進程都有自己獨立的地址空間。 | 不擁有系統資源,但共享其所屬進程的全部資源。每個線程擁有自己獨立的棧和寄存器。 |
開銷 | 大。創建、銷毀、切換進程需要分配和回收獨立的內存空間、資源表等,開銷較大。 | 小。創建、銷毀、切換線程只需分配棧和寄存器,共享同一片內存空間,開銷遠小于進程。 |
通信方式 | 復雜。進程間通信(IPC)需要借助操作系統提供的機制,如:管道、消息隊列、共享內存、信號量、Socket等。 | 簡單。線程間通信非常方便,因為它們共享進程的全局變量、堆等數據,直接讀寫即可。但需要同步機制(如互斥鎖)來避免沖突。 |
獨立性 | 高。一個進程崩潰后,在保護模式下一般不會影響其他進程。穩定性高,隔離性好。 | 低。一個線程崩潰會導致整個進程崩潰,從而影響該進程下的所有其他線程。穩定性低,相互影響。 |
性能影響 | 進程間切換涉及地址空間的切換,CPU高速緩存(Cache)失效率高,性能損耗大。 | 線程切換只在同一地址空間內,CPU高速緩存不易失效,性能損耗小。 |
并發性 | 進程之間可以并發執行。 | 線程之間不僅可以并發執行,甚至可以實現真正的并行(在多核CPU上)。 |
從操作系統角度理解
操作系統會為每個進程維護一個進程控制塊(PCB),這是一個龐大的數據結構,記錄了進程的所有信息(PID、狀態、優先級、內存指針等)。而線程也有自己的線程控制塊(TCB),但它記錄的信息要少得多(主要是線程ID、寄存器、棧指針等),因為它的大部分資源信息都指向其所屬的PCB。
當進行進程切換時,操作系統需要切換整個地址空間(更換頁表),這是一個相對沉重的操作。而線程切換只需切換線程的私有數據(如棧和寄存器),效率高得多。
總結與聯系
-
包含關系:一個進程至少包含一個線程(主線程),也可以擁有多個線程。
-
設計目的:
-
進程?是為了更好地使多道程序并發執行,提高資源利用率和系統吞吐量。它強調的是“資源分配的獨立性”。
-
線程?是為了減少程序并發執行時的時空開銷,提高操作系統的并發性能。它強調的是“計算執行的并行性”。
-
-
如何選擇:
-
需要安全穩定、任務之間隔離要求高時(例如Chrome瀏覽器每個標簽頁是一個獨立進程),用進程。
-
需要極致性能、大量數據共享、頻繁切換時(例如Web服務器同時處理多個請求、視頻解碼、文字處理軟件的后臺保存和打字),用多線程。
-
簡單來說,進程是資源的容器,而線程是CPU執行的單元。線程依托于進程而存在,共享進程的資源,使得同一個應用程序內的多個任務可以更高效地協作。
線程和進程的代碼
線程:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<strings.h>
#include<unistd.h>
#include<ctype.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
#include<pthread.h>
#define SERV_PORT 8000
#define MAXLINE 80//打印報錯信息
#define prrexit(msg){ \perror(msg); \exit(1); \}//子線程
void *up_server(void *arg){//獲取自己的線程id,自我釋放pthread_detach(pthread_self());//進行安全的類型轉換int connfd=(int)(intptr_t)arg;char buff[MAXLINE];int n,i;while(1){n=read(connfd,buff,MAXLINE);if(n<=0){perror("read error or connections closed");break;}write(1,buff,n);if(strncmp(buff,"quit",4)==0){break;}for(i = 0; i < n ; i++)buff[i]=toupper(buff[i]);write(connfd,buff,n);}close(connfd);//正常退出return (void *)0;
}int main(){struct sockaddr_in serveraddr,claddr;int listenfd, connfd;socklen_t claddr_len;// char buff[MAXLINE];char str[INET_ADDRSTRLEN];int n,i;listenfd =socket(AF_INET,SOCK_STREAM,0);if(listenfd<0){prrexit("socket");}//服務器ip地址,端口初始化bzero(&serveraddr,sizeof(serveraddr));serveraddr.sin_family=AF_INET;serveraddr.sin_port = htons(SERV_PORT);serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr))<0)prrexit("bind");if(listen(listenfd,3)<0)prrexit("listen");printf("Accepting connections...\n");while(1){claddr_len= sizeof(claddr);connfd=accept(listenfd,(struct sockaddr *)&claddr,&claddr_len);if(connfd<0)prrexit("accept");printf("received from %s:%d\n",inet_ntop(AF_INET,&claddr.sin_addr,str,sizeof(str)),ntohs(claddr.sin_port));/*多進程pid_t pid= fork();if(pid<0){prrexit("fork");}//父進程 :等待 創建連接if(pid > 0){close(connfd);//回收進程資源while(waitpid(-1,NULL,WNOHANG)>0){ };continue;}close(listenfd);*///多線程pthread_t tid;pthread_create(&tid,NULL,up_server,(void *)(intptr_t)connfd);printf("new thread is %#lx\n",tid);}return 0;
}
補充一下,因為實現線程時候調用了pthread庫的函數,所以需要額外鏈接上 -lpthread庫用以實現。
進程:
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<strings.h>
#include<unistd.h>
#include<ctype.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>#define SERV_PORT 8000
#define MAXLINE 80//打印報錯信息
#define prrexit(msg){ \perror(msg); \exit(1); \
}int main(){struct sockaddr_in serveraddr,claddr;int listenfd, connfd;socklen_t claddr_len;char buff[MAXLINE];char str[INET_ADDRSTRLEN];int n,i;listenfd =socket(AF_INET,SOCK_STREAM,0);if(listenfd<0){prrexit("socket");}//服務器ip地址,端口初始化bzero(&serveraddr,sizeof(serveraddr));serveraddr.sin_family=AF_INET;serveraddr.sin_port = htons(SERV_PORT);serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);if(bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr))<0)prrexit("bind");if(listen(listenfd,3)<0)prrexit("listen");printf("Accepting connections...\n");while(1){claddr_len= sizeof(claddr);connfd=accept(listenfd,(struct sockaddr *)&claddr,&claddr_len);if(connfd<0)prrexit("accept");printf("received from %s:%d\n",inet_ntop(AF_INET,&claddr.sin_addr,str,sizeof(str)),ntohs(claddr.sin_port));pid_t pid= fork();if(pid<0){prrexit("fork");}//父進程 :等待 創建連接if(pid > 0){close(connfd);//回收進程資源while(waitpid(-1,NULL,WNOHANG)>0){ };continue;}close(listenfd); //讀,寫,返回while(1){n=read(connfd,buff,MAXLINE);if(n<=0){perror("read error or connections closed");break;}write(1,buff,n);if(strncmp(buff,"quit",4)==0){break;}for(i = 0; i < n ; i++)buff[i]=toupper(buff[i]);write(connfd,buff,n);}close(connfd);}return 0;
}