线程的基本概念
- 线程就是进程中的执行路线,即进程内部的控制序列,或者说是进程的子任务(进程就是正在运行的程序,他是资源分配的基本单位)
- 线程就是轻量级的,没有自己独立的内存资源,使用的是进程的代码段、数据段、BSS段、堆(注意没有栈)、环境变量表、命令行参数、文件描述符、信号处理函数、工作目录、用户ID、组ID等资源。
- 进程拥有自己独立的栈,也就是有自己独立的局部变量
- 一个进程中可以同时拥有多个线程,即同时被系统调度的多条执行路线,但至少要有一个主线程。
线程的基本特点
- 线程是进程的实体,线程可以作为系统独立的调度和分配的基本单位
- 线程有不同的状态,系统提供了多种线程控制的原语(控制方法)
- 线程没有自己的资源,唯一有的只是栈空间,只拥有从属于进程的全部资源,所有资源分配都是面向进程的
- 一个进程中可以有多个线程同时执行(并行执行),他们可以执行相同的代码,也可以是不同的代码
- 同一进程内的线程都在同一个地址空间内活动(0~4G),相对于多进程,多线程的系统开销小,任务切换快。
- 多进程协同工作时互相之间需要通信;线程协调工作时也需要通信,但不需要类似IPC的特殊通信机制,简单而高效
- 每个线程拥有自己独立的线程ID,寄存器信息,函数栈
- 线程之间也存在优先级
线程和进程的区别
POSIX线程
- 早期的UNIX系统没有线程这个概念,所以没有线程。各计算机的厂商提供了自己的线程库,不易移植
- 在1995年定义了统一的线程编程接口。POSIX线程,即pthread。
- pthread包含一个头文件
pthread.h
,一个共享库lib怕thread.so
, - 功能
- 线程管理:创建/销毁、分离/联合、设置/获取属性
- 线程同步(互斥):互斥量(互斥锁)、条件变量、信号量(与进程的信号量不同,但使用机制类似)
线程函数
-
线程的创建
#include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
- 功能:创建线程
thread
:获取线程IDattr
:创建线程是所需要的属性设置 如果为NULL按照默认方式创造线程start_routine
: 线程的入口函数arg
:给线程入口函数传递的参数- 实例
#include <pthread.h> void* start_run(void* arg) { printf("%s\n",(char*)arg); while(1) { printf("*\n"); fflush(stdout); sleep(1); } } int main( { char str[10] = "aaaaa" pthread_t pid; pthread_create(&pid,NULL,start_run,str); while(1) { printf("#"); sleep(1); } } //-lpthread
-
等待联合线程结束
#include <pthread.h> int pthread_join(pthread_t thread, void **retval);
- 功能:等待线程结束,获取线程入口函数的返回值(线程结束时函数才返回)
thread
:线程IDretval
:指针变量的地址,用于获取线程入口函数的返回值。- 线程入口函数在返回数据时,不能返回指向私有栈空间的指针。如果获取到的是指向堆的指针,那等待者要负责释放指针
- 例子
#include <stdio.h> #include <unistd.h> #include <pthread.h> void* start_run(void* arg) { char* str = "dididi";//生成在代码段 //char str[] = "dididi";生成在线程的栈,线程结束后数据销毁无法返回 return str; } int main( { pthread_t pid; pthread_create(&pid,NULL,start_run,NULL); void* ptr = NULL; pathread_join(pid,&ptr); printf("%s\n",(char*)ptr); }