进程和线程
进程:一个正在执行的程序,是资源分配的最小单位 线程:程序执行的最小单位,系统独立调度和分配CPU的基本单位,是进程中的一个实体,一个进程具有多个线程,线程共享进程中的所有资源,每个线程本身包含一点必不可少的资源
并发,并行,同步,异步
|并发| 并行 |同步|异步|
|--|--|--|--|
| 看起来同时发生(单核) | 多条指令多个处理器同时执行 |防止同时发生的一种机制|任何两个彼此独立的操作是异步的,表明事件独立的发生|
创建线程(注意编译的时候需要 -lpthread )
#include "apue.h"
#include "pthread.h"
void print_id ( char * s) {
pid_t pid;
pthread_t tid;
pid = getpid ( ) ;
tid = pthread_self ( ) ;
printf ( "%s pid is %u ,tid is 0x%lx \n" , s, pid, tid) ;
}
void * thread_fun ( void * arg) {
print_id ( arg) ;
return ( void * ) 0 ;
}
int main ( ) {
pthread_t ntid;
int err;
err = pthread_create ( & ntid, NULL , thread_fun, "newthread" ) ;
if ( err!= 0 ) {
printf ( "create fail\n" ) ;
return 0 ;
}
print_id ( "main thread :" ) ;
sleep ( 2 ) ;
return 0 ;
}
线程的几种状态
状态 含义 备注 就绪 线程能够运行,但是在等待可用的处理器 线程刚刚创建的时候就处于就绪状态,当被解除阻塞状态后也会处于就绪状态,当一个运行的线程被抢占的时候,立即又回到就绪状态 运行 线程正在运行,在多核系统中,可能有多个线程在运行 阻塞 线程在等待处理器以外的其他条件 线程会在以下情况发生阻塞:试图加锁一个已经被锁住的互斥量,等待某个条件变量,调用singwait等待尚未发生的信号,执行无法完成的IO信号,由于内存页错误 终止 线程从启动函数中返回,或者调用pthread_exit函数,或者被取消 线程通常在启动函数中返回来中止自己,或者调用pthread_exit退出,或者取消线程
主线程
当C程序运行的时候,首先运行main函数,这个特殊的执行流被称为初始线程或者主线程,可以在初始线程中做任何普通线程可以做的事情
主线程示例代码
#include "apue.h"
#include "pthread.h"
typedef struct {
int age;
char name[ 20 ] ;
} Student ;
Student student;
void * thread_fun ( void * stu ) {
printf ( "age is %d,name is %s\n" , student. age, student. name) ;
return ( void * ) 0 ;
}
int main ( int argc , char * argv[ ] ) {
pthread_t tid;
int err;
student. age = 20 ;
memcpy ( student. name, "zhangsan" , 20 ) ;
err= pthread_create ( & tid, NULL , thread_fun, ( void * ) ( & student) ) ;
if ( err!= 0 ) {
printf ( "create a new thread failed\n" ) ;
return 0 ;
}
int i ;
for ( i= 0 ; i< argc; i++ ) {
printf ( "main thread arg is %s\n" , argv[ i] ) ;
}
sleep ( 1 ) ;
return 0 ;
}
线程退出代码
#include "apue.h"
#include "pthread.h"
void * thread_fun ( void * arg) {
if ( strcmp ( "1" , ( char * ) arg) == 0 ) {
printf ( "new thread return!\n " ) ;
return ( void * ) 1 ;
}
if ( strcmp ( "2" , ( char * ) arg) == 0 ) {
printf ( "new thread pthread_exit!\n " ) ;
pthread_exit ( ( void * ) 2 ) ;
}
if ( strcmp ( "3" , ( char * ) arg) == 0 ) {
printf ( "new thread exit!\n " ) ;
exit ( 3 ) ;
}
}
int main ( int argc , char * argv[ ] ) {
int err;
pthread_t tid;
err = pthread_create ( & tid, NULL , thread_fun, ( void * ) argv[ 1 ] ) ;
if ( err!= 0 ) {
printf ( "create new thread failed\n" ) ;
return 0 ;
}
sleep ( 1 ) ;
printf ( "main thread \n" ) ;
return 0 ;
}
主线程和普通线程
区别 主线程 普通线程 退出 主线程的特殊性在于,在main函数返回的时候,会导致进程结束,进程内的所有线程也会结束,可以在主线程中调用pthread_exit
函数,这样进程就会等待所有线程结束的时候才会结束 线程结束可以:1. 从启动例程中返回,返回值是线程的退出码,2线程可以被同一个进程中的其他线程取消,3. 线程调用pthread_exit(void* rval)
函数,*rval是退出码 接收参数 主线程接收参数的方式是argc
和argv
普通的线程只有一个void*
运行堆栈 绝大多数情况下主线程在默认堆栈上运行,这个堆栈可以增长到足够的高度 而普通线程的堆栈是受限制的,一旦溢出就会发生错误 创建 主线程随着进程的创建而创建 其他线程可以调用函数来创建(主要调用pthread_create
)