【总结】进程,线程,并发
2012-04-28 19:49
204 查看
进程,线程,并发
文/xichen 2011年3月
写这个文档是希望通过,概念的理解和程序的测试认识“进程”“线程”“并发等概念”。关于基本概念不想写太多,操作系统每本书里面都会重点讲的,看了一些资料,有一些自己的理解。进程是表示资源分配的基本单位,它运行起来需要的是系统资源,是系统给他分配的一些资源。至于是不是系统调度的基本单位,实际上跟操作系统内核是有关系的,在Mac、Windows NT等采用微内核结构的操作系统中,进程的功能发生了变化:它只是资源分配的单位,而不再是调度运行的单位。在微内核系统中,真正调度运行的基本单位是线程。因此,实现并发功能的单位是线程。有必要说下,进程需要的资源和线程需要的资源。跟操作系统有关,但是也很相像。
其实对于我本人而言我是很希望知道在操作系统内部究竟是怎么给进程和线程分配资源的:
进程:查到了一个很好的关于linux0.11中的进程的数据结构
http://www.cppblog.com/jake1036/archive/2010/11/13/133530.html
线程:一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成。
线程自己的资源:栈,私有数据,但是多个线程是共享内存单元的,(是有一定的安全问题的)。
关于线程的数据结构:http://www.programfan.com/blog/article.asp?id=44349
操作系统创建线程实际上就是在处理器调度的时候能够在最小的资源代价下切换任务。一个说法是:进程切换比线程切换开销大是因为进程切换时要切页表,而且往往伴随着页调度,因为进程的数据段代码段要换出去,以便把将要执行的进程的内容换进来。本来进程的内容就是线程的超集。而且线程只需要保存线程的上下文(相关寄存器状态和栈的信息)就好了,动作很小。在多处理器下,又允许几个线程各自在单独处理上进行,这样能够很好的实现这种并发性。
关于并发,这里给出一个我见过的最好的一个定义:如果逻辑控制流在时间上重叠,那么它们就是并发。PS:逻辑控制流:当我们在使用调试器单步地执行我们的程序时,会看到一系列的PC(程序计数器)的值,这些值唯一地对应于包含在我们程序的可执行目标文件中的指令或者是包含在运行时动态链接到我们的共享对象中的指令,这个PC值的序列就叫做逻辑控制流。
实际上,很多时候并发性是一种内核用来运行多个应用程序的策略,但是并不局限于内核。应用级并发的应用程序:分别是基于进程的,I/O多路复用,线程的并发。
进程并发和线程并发有很多区别,具体有一个很好的对比参考http://programmerdigest.cn/2010/08/1096.html
多线程的编程主要涉及到进程的控制和进程通信(IPC),如果写比较小的代码都要考虑进程同步或者其他神马问题,后面提到的代码都是些多线程的。原理倒是一样的。
关于多线程的创建是会遇到下面的一个问题的:
#include<windows.h> #include<stdio.h> #define MAX_THREADS 5 typedef struct _THREAD_PARAM { DWORD i; DWORD dwRandom; DWORD dwData; }THREAD_PARAM,*LPTHREAD_PARAM; DWORD WINAPI ThreadProc( LPVOID lpParam) { LPTHREAD_PARAM pData; pData = (LPTHREAD_PARAM)lpParam; printf("TID=%u,\t parameters = %u,%u,%u\n", GetCurrentThreadId(), pData->i,pData->dwRandom,pData->dwData); HeapFree(GetProcessHeap(),0,pData); return 0; } int main() { LPTHREAD_PARAM pData; DWORD dwThreadId[MAX_THREADS]; HANDLE hThread[MAX_THREADS]; int i; for(i=0;i<MAX_THREADS;i++) { pData=(LPTHREAD_PARAM)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(THREAD_PARAM)); if (pData == NULL) { printf("heapallc error;\n"); ExitProcess(2); } pData->i= i; pData->dwRandom=rand(); pData->dwData=100; hThread[i]=CreateThread(NULL,0,ThreadProc,pData,0,&dwThreadId[i]); /* 解决办法: //等待所有线程结束 WaitForMultipleObjects(MAX_THREADS,hThread,TRUE,INFINITE); for(i=0;i<MAX_THREADS;i++) { CloseHandle(hThread[i]); } */ if(hThread[i]==NULL) { ExitProcess(i); } } return 0; } |
编译运行以上程序,目的是创建5个线程,但是实际上,运行之后在我的机器上只能够得到2个线程,在其他机器上能够出现4个线程,这是因为有的线程还没执行完,主线程就退出了,这个说法我觉得是很肤浅的,没有更多的解释,具体的解决办法也是比较简单,就是等待线程全部完成再退出。 但是对此我有疑问: 1.这个程序能够运行几个线程跟什么有关? 2.主线程究竟能够运行多久?极端的去想,创建一个线程,创建1W个线程会有哪些具体的不同? ………………….. ………………….. |
#include <pthread.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #define TN 3 /*numbers of threads*/ void routine(void * arg); int main() { pthread_t thread[TN]; int retval,i; char msg[TN][10]; puts("this is main thread!."); for(i = 0;i<TN;i++) { sprintf(msg[i],"thread %d",i); retval = Pthread_create(&thread[i],NULL,(void *)routine,msg[i]); if(retval!= 0) { perror("thread create failed."); exit(1); } } for(i = 0;i<TN;i++) Pthread_join(thread[i],NULL); puts("main thread exiting."); return 0; } void routine(void * arg) { int j; for(j=0 ; j<5;j++) { sleep(1+(int)(5.0*rand()/(RAND_MAX+1.0)));/*睡眠时间,通过随机数进行控制*/ printf("%s:",(char *)arg); printf("% d\n",j); } return; } |
类似的我在WINDOWS下面也改写了这个程序,上代码:
#include <process.h> #include <stdio.h> #include <windows.h> void thread_proc(void *arg) { printf("a thread %d,id is:",arg); _endthread(); } int main() { unsigned pid; int count=0; while(count<5)//线程数 { _beginthreadex(NULL,0, (unsigned (__stdcall *) (void *))thread_proc,(void *)count,0,&pid);//创建线程 Sleep(1+(int)(10.0*rand()/(RAND_MAX+1.0))); //Sleep( 10); /*如果你选择一个固定时间,比如10秒钟,也是可以的,但是并不能很好地确定该数值的大小, 但是我不知道酱紫说对还是不对,我觉得这个可能跟操作系统的那个调度算法有关,比如时间片调度的话,据说一个时间片可以 调度10个进程。后面提到,肯定还是要写程序测试一下地…… */ printf("%d\n",pid); count++; } return 0; } /*关键函数 uintptr_t _beginthreadex( void *security, unsigned stack_size, unsigned ( *start_address )( void * ), void *arglist, unsigned initflag, unsigned *thrdaddr ) 其实…… _endthread()也很关键,往往收尾的好人总是被大家遗忘…… */ |
http://hi.baidu.com/kings0527/blog/item/11838d02a1b3bbe608fa93ff.html
很多时候的很多结果,不一定如我们所想,虽然仔细分析可以得到正确的结果,但是,但是悲剧的是,很多时候我们喜欢想当然
代码,一个很好的关于竞争的例子:
#include"csapp.h" #define N 4 void *thread(void *vargp); int main() { pthread_t tid ; int i; for(i = 0; i<N; i++) Pthread_create(&tid[i],NULL,thread,&i); for(i = 0; i<N; i++) Pthread_join(tid[i],NULL); exit(0); } void *thread(void *vargp) { int myid = *((int *)vargp); printf("this is from thread %d",myid); return NULL; } |
相关文章推荐
- 进程、线程知识点总结和同步(消费者生产者,读者写者三类问题)、互斥、异步、并发、并行、死锁、活锁的总结
- 进程、线程知识点总结和同步(消费者生产者,读者写者三类问题)、互斥、异步、并发、并行、死锁、活锁的总结
- Python中并发、进程、线程的总结
- 并发编程总结1——java线程基础1
- php源码之路第八章第一节 (线程,进程和并发)
- java核心知识点学习----并发和并行的区别,进程和线程的区别,如何创建线程和线程的四种状态,什么是线程计时器
- java中的进程,线程,线程池总结
- 线程与进程,多线程,多进程,线程并发,线程并行
- 线程与进程(总结)
- 你真的了解:IIS连接数、IIS并发连接数、IIS最大并发工作线程数、应用程序池的队列长度、应用程序池的最大工作进程数 吗?
- 进程和线程之间的区别和联系总结
- Java总结(九)——(线程模块 一(线程的创建(方法一)与启动,线程状态与生命周期,进程与线程))
- [面试]进程与线程的区别联系,并发和并行的区别
- 进程线程及堆栈关系的总结
- android进程和线程使用总结
- 进程与线程、并发与并行、同步与异步的区别
- Java线程总结(五):并发包------线程池Executors
- 【转载】Java并发编程1:进程和线程之由来
- Java线程总结(十三):并发包------线程返回结果Callable和 Future
- 进程和线程间的通信方式总结-篇一(转载)