多线程编程1——基础知识
来源:互联网 发布:淘宝的渠道管理在哪里 编辑:程序博客网 时间:2024/06/05 22:50
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属于一个进程的其他的线程共享进程拥有的全部资源。
Linux进程创建一个新线程时,线程将拥有自己的栈(因为线程有自己的局部变量),但与它的创建者共享全局变量、文件描述符、信号句柄和当前目录状态。
Linux通过fork创建子进程与创建线程之间是有区别的:fork创建出该进程的一份拷贝,这个新进程拥有自己的变量和自己的PID,它的时间调度是独立的,它的执行几乎完全独立于父进程。
进程可以看成一个资源的基本单位,而线程是程序调度的基本单位,一个进程内部的线程之间共享进程获得的时间
线程相对于进程的优点:
1、和进程相比,它是一种非常”节俭”的多任务操作方式。在linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种”昂贵”的多任务工作方式。
2、运行于一个进程中的多个线程,它们之间使用相同的地址空间,而且线程间彼此切换所需时间也远远小于进程间切换所需要的时间。据统计,一个进程的开销大约是一个线程开销的30倍左右。
3、线程间方便的通信机制。对不同进程来说,它们具有独立的数据空间,要进行数据的传递只能通过进程间通信的方式进行,这种方式不仅费时,而且很不方便。线程则不然,由于同一进城下的线程之间贡献数据空间,所以一个线程的数据可以直接为其他线程所用,这不仅快捷,而且方便。
4、使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。
5、改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序才会利于理解和修改。
简单的多线程操作
1、线程创建
#include <pthread.h>int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);//thread:指向pthread_t类型的指针,用于引用新创建的线程。//attr:用于设置线程的属性,一般不需要特殊的属性,所以可以简单地设置为NULL。//*(*start_routine)(void *):传递新线程所要执行的函数地址。//arg:新线程所要执行的函数的参数。//调用如果成功,则返回值是0,如果失败则返回错误代码。
2、线程ID的获取
pthread_t pthread_self(void);//返回当前线程的ID
3、线程终止
void pthread_exit(void *retval);//retval:返回指针,指向线程向要返回的某个对象。
4、线程等待
int pthread_join(pthread_t th, void **thread_return);//th:将要等待的线程,线程通过pthread_create返回的标识符来指定。//thread_return:一个指针,指向另一个指针,而后者指向线程的返回值。不需要返回值则为NULL
5、线程分离
int pthread_detach(pthread_t thread);//成功返回0。失败返回错误值
除了局部变量以外,所有其他变量都将在一个进程中的所有线程之间共享。
线程没有像进程那样的父子关系,仅有属于同一个进程的“同组”关系(进程实际上代表的是一个线程组)。
在POSIX线程模型中,主线程可以创建一个新线程A,新线程A又可以创建另一个新线程B,线程A和B本身没有父子关系,只是同属于一个进程。
等待线程结束的pthread_join()操作可以由任何一个同组的线程发起,不必是主线程。另外,如果主线程退出,即进程退出,则所有的线程也会随之退出。
案例:
1、线程创建
void *thread_run(void* a){ while (1) { sleep(1); printf ("线程 函数\n"); }}int main(){ pthread_t thread_id; int ret = pthread_create(&thread_id, NULL, thread_run, NULL); if (ret != 0) { perror ("pthread_create"); return -1; } while (1) { sleep(1); printf ("main 函数\n"); } return 0;}
2、参数传递
struct data{ int a; int b;};void *thread_run(void* a){ struct data *value = (struct data*)a; printf ("线程接收到参数: %d, %d\n", value->a, value->b); int ret = value->a + value->b; // 不能通过 pthread_exit 返回栈上变量的地址 pthread_exit((void*)ret); // pthread_exit((void*)&ret);}pthread_t func(){ struct data value; value.a = 10; value.b = 20; pthread_t thread_id; // 给线程传参要注意 栈上的变量的生命周期 int ret = pthread_create(&thread_id, NULL, thread_run, (void *)&value); if (ret != 0) { perror ("pthread_create"); return -1; } return thread_id;}int main(){ int *result; pthread_t thread_id = func(); printf ("等待线程结束\n"); pthread_join(thread_id, (void **)&result); printf ("result = %d\n", *result); return 0;}
- 多线程编程1——基础知识
- Java多线程编程总结笔记——一多线程基础知识
- Java多线程编程总结笔记——一多线程基础知识
- Java多线程编程总结笔记——02多线程基础知识
- 多线程编程学习笔记之一——基础知识
- 基础知识——多线程
- Java多线程编程1----基础知识--守护线程
- java多线程编程核心技术1-Thread基础知识
- 多线程编程基础知识
- 多线程编程基础知识
- 多线程编程基础知识
- 多线程编程基础知识
- 多线程编程基础知识
- 多线程编程基础知识
- 多线程编程基础知识
- 多线程编程的基础知识
- 多线程编程基础知识
- 多线程编程基础知识
- HDU 1102 Constructing Roads(prim求最小生成树)
- Ubuntu uninstalling software completely(include purge configuration and files)
- [HDU]1520 Anniversary party
- JS直接修改CSS属性/id属性/class属性
- 基于同步器的合并接口实现
- 多线程编程1——基础知识
- EasyMall第十天
- druid 查询接口的使用
- PyCharm激活
- springboot学习一(环境搭建入门学习)
- Bigtable: A Distributed Storage System for Structured Data : part3 API
- TortoiseSVN设置比较工具为 Beyond Compare
- oracl 导出与导入字节码不一样 ORA-12899报错
- 冒泡排序,选择排序,插入排序,快排