进程:硬盘上的一个静态的程序在内存中动态执行的实例
操作系统分配资源的基本单位
每个进程拥有自己独立的内存空间。
在操作系统下构成单独执行流的单位
线程:轻量级进程,
是操作系统调度的最小单元,
线程只能存在于进程中,
进程死亡时其中的线程也会死亡
在进程下构成单独执行流的单位
使用进程的优势:
(1)CPU时分复用,单核心CPU可以实现宏观上的并行(多进程实际是宏观上并行,微观上串行)
(2)实现多任务系统需求(多任务的需求是客观的)
进程技术的劣势
(1)进程间切换开销大
(2)进程间通信麻烦而且效率低
(3)创建进程有一定的开销
线程
(1)线程间切换比进程间切换快
(2)同一进程的多个线程之间很容易高效率通信
(3)多线程在多核心CPU上面更有优势 (多核心cpu上可以一个核心运行一个线程,但是进程却不是)
(4)可以像进程一样被系统调度
注:每个进程的内存空间都有自己的数据区、堆、栈。进程中的线程之间只是分离栈,共享了堆与数据区,因此线程间切换时就不需要切换堆与数据区,他们甚至可以利用数据区与堆实现通信
线程的创建
参数thread 指向保存新创建线程ID的变量的指针
参数attr 用于传递线程属性的参数,传递NULL时,创建默认属性线程
参数start_routine 指向参数类型为void *返回值为void *的函数指针,即线程运行函数的起始地址
参数arg 线程运行函数的参数
restrict关键字,参考 http://blog.chinaunix.net/uid-22197900-id-359209.html
线程正确的回收方式
1.使用pthread_join()函数回收相关内存区域。
2.可以调用 pthread_detach() 函数分离线程。
3.使用线程属性。
pthread_join函数
参数value_ptr 退出线程的返回值。
注意:1、应该定义一个以及指针然后在pthread_join中传递一级指针的地址,而不是指针定义二级指针然后直接传递二级指针
参考 对线程等待函数pthread_join二级指针参数分析: http://www.cnblogs.com/zhangfeionline/p/5975272.html
2、函数pthread_join在调用后会一直阻塞,直到指定ID的线程死亡
示例:
pthread_detach函数
设置线程属性:
参考: pthread_create会导致内存泄露 http://blog.chinaunix.net/uid-22663647-id-1771775.html
注:要使用多线程技术,应该在编译时添加参数 -lpthread
进程和线程的关系与区别: http://blog.csdn.net/yaosiming2011/article/details/44280797
编程思想之多线程与多进程(1)——以操作系统的角度述说线程与进程: http://blog.csdn.net/luoweifu/article/details/46595285
深入理解进程和线程: http://www.cnblogs.com/tiankong101/p/4229584.html
转载--多进程和多线程的优缺点: http://www.cnblogs.com/Yogurshine/p/3640206.html
操作系统分配资源的基本单位
每个进程拥有自己独立的内存空间。
在操作系统下构成单独执行流的单位
线程:轻量级进程,
是操作系统调度的最小单元,
线程只能存在于进程中,
进程死亡时其中的线程也会死亡
在进程下构成单独执行流的单位
使用进程的优势:
(1)CPU时分复用,单核心CPU可以实现宏观上的并行(多进程实际是宏观上并行,微观上串行)
(2)实现多任务系统需求(多任务的需求是客观的)
进程技术的劣势
(1)进程间切换开销大
(2)进程间通信麻烦而且效率低
(3)创建进程有一定的开销
线程
(1)线程间切换比进程间切换快
(2)同一进程的多个线程之间很容易高效率通信
(3)多线程在多核心CPU上面更有优势 (多核心cpu上可以一个核心运行一个线程,但是进程却不是)
(4)可以像进程一样被系统调度
注:每个进程的内存空间都有自己的数据区、堆、栈。进程中的线程之间只是分离栈,共享了堆与数据区,因此线程间切换时就不需要切换堆与数据区,他们甚至可以利用数据区与堆实现通信
线程的创建
int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void*(*start_routine)(void*), void *restrict arg);
//成功返回0,失败返回其他值
参数thread 指向保存新创建线程ID的变量的指针
参数attr 用于传递线程属性的参数,传递NULL时,创建默认属性线程
参数start_routine 指向参数类型为void *返回值为void *的函数指针,即线程运行函数的起始地址
参数arg 线程运行函数的参数
restrict关键字,参考 http://blog.chinaunix.net/uid-22197900-id-359209.html
线程正确的回收方式
1.使用pthread_join()函数回收相关内存区域。
2.可以调用 pthread_detach() 函数分离线程。
3.使用线程属性。
pthread_join函数
int pthread_join(pthread_t thread, void **value_ptr); //成功返回0,失败返回其他值
参数thread
等待退出线程的线程号。
参数value_ptr 退出线程的返回值。
注意:1、应该定义一个以及指针然后在pthread_join中传递一级指针的地址,而不是指针定义二级指针然后直接传递二级指针
参考 对线程等待函数pthread_join二级指针参数分析: http://www.cnblogs.com/zhangfeionline/p/5975272.html
2、函数pthread_join在调用后会一直阻塞,直到指定ID的线程死亡
示例:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
void *thread_main(void *arg);
int main(int argc, char *argv[])
{
pthread_t t_id;
int thread_param = 5;
void *thr_ret = NULL; //定义一级指针,而不是void **thr_ret
if( 0 != pthread_create(&t_id, NULL, thread_main, (void *)&thread_param) )
{
puts("pthread_create() error");
return -1;
}
if(0 != pthread_join(t_id, &thr_ret) ) //不是pthread_join(t_id, thr_ret),应该定义一级指针
{
puts("pthread_join() error");
return -1;
}
printf("Thread return message: %s\n", (char*)thr_ret);
free(thr_ret);
puts("end of main");
return 0;
}
void *thread_main(void *arg)
{
int i = 0;
int cnt = *((int *)arg);
char *mes = (char *)malloc(sizeof(char) * 50);
strcpy(msg, "Hello, I'm thread~\n ");
for (i = 0; i < cnt; i++)
{
sleep(1);
puts("running thread");
}
return (void *)msg; //亦可使用pthread_exit((void *)msg),建议使用后者
//参考:多线程:线程的返回retrun和pthread_exit http://blog.csdn.net/kangear/article/details/8516114
}
pthread_detach函数
int pthread_detach(pthread_t tid); //成功返回0,失败返回其他值
参数tid
需要分离的线程的ID
设置线程属性:
参考: pthread_create会导致内存泄露 http://blog.chinaunix.net/uid-22663647-id-1771775.html
注:要使用多线程技术,应该在编译时添加参数 -lpthread
进程和线程的关系与区别: http://blog.csdn.net/yaosiming2011/article/details/44280797
编程思想之多线程与多进程(1)——以操作系统的角度述说线程与进程: http://blog.csdn.net/luoweifu/article/details/46595285
深入理解进程和线程: http://www.cnblogs.com/tiankong101/p/4229584.html
转载--多进程和多线程的优缺点: http://www.cnblogs.com/Yogurshine/p/3640206.html