一、线程起源
线程的产生基于通过共享公共的内存空间来交换数据可提高协作进程间的通信效率这一思想。线程是程序执行流的最小单元,是进程中的一个实体,一个标准的线程由线程ID、寄存器集合和堆栈组成。是被系统独立调度和分配的基本单位。线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。
在某一时刻,进程内只有一个称为控制线程的线程能被执行。当进程的CPU时间片开始时,操作系统根据线程在其他进程线程中的优先级、程序代码的复杂性、该线程被访问的频率等因素为进程选择控制线程。
注意:线程上下文的切换使用系统资源,所以将进程中的线程数保持在为完成预期任务所必须的最少数目是一种良好的编程习惯。
二、线程如何创建?
线程用thread_create函数创建,当pthread_create函数返回时,当前控制线程继续执行pthread_create调用下一条程序指令。
当新线程成为控制线程时,它将执行由调用pthread_create的参数start_routine指定的函数的第一条程序指令。
一旦线程被创建,它将执行直到所有的start_routine程序指令都被执行,或者return语句被执行,或者创建该线程的进程结束。
因为线程之间独立运行,因此给定的线程的确切结束时间是不可知的,称为异步事件。通过等待线程结束并且完成所有的清理工作,pthread_join函数可使线程事件同步,如此线程可以等待另一个线程的结束来实现线程之间的合作。
注意:1.要使用pthread_join和pthread_create函数,必须包含pthread.h头文件.
2.linux下面编译的时候,要用 gcc file.c -lpthread 命令。
下面来看一段代码:
#include<pthread.h> int main() { pthread_t tid; ... pthread_create(&tid,NULL,tsub,NULL); //成功创建返回0;失败,返回大于0的值 printf("Main thread after pthread_create()\n"); ... return 0; } //当新线程成为控制线程的时候,tsub函数开始执行第一条语句printf. void* tsub(void* arg) { printf("New thread first executable statement\n"); ... return NULL; }
三、线程如何实现同步?
当进程多于一个执行线程的时候,就有可能出现某个线程试图改变一个变量的值,与此同时另一个线程正试图获得该变量的值。
而我们已经直到,在实际中,两个线程不能同时运行,因为每次只有一个能成为控制线程。所以这个时候,就会产生数据不一致的现象。所谓的数据不一致就是指,由于进程中的一个线程访问共享资源,而另一个线程正在修改共享资源而导致的数据错误。
那么如何避免这种错误呢?我们会采用互斥锁或者互斥量的机制,即通过使用加锁和释放锁的机制,限制在任意给定的时刻共享资源只能由一个线程访问而实现。互斥量可以在访问共享资源之前加锁,访问之后释放。
可以看下面一段代码:
#include<pthread.h> ... pthread_mutex_t lock; ... int main(void) { ... //初始化互斥量函数,成功向进程返回0,失败返回大于0的值 if(pthread_mutex_init(&lock,NULL)!=0) printf("Error initializing mutex lock\n"); ... //锁定互斥量函数,成功返回0,失败返回大于0的值 if(pthread_mutex_lock(&lock)!=0) printf("Error locking mutex\n"); ... //释放互斥锁的函数,成功返回0,失败返回大于0的值 if(pthread_mutex_unlock(&lock)!=0) printf("Error unlocking mutex\n"); return 0; }
附录:
一个完整的多线程的简单程序,以加深理解:
1 #include<pthread.h> 2 #include<stdio.h> 3 #include<unistd.h> 4 5 void* thread(void* argument); 6 intdata; 7 pthread_mutex_t lock; 8 9 intmain() 10 { 11 pthread_t tid; 12 intloop; 13 printf("Primary Thread Started ID %lu\n",pthread_self());//display the p rimary thread id; 14 data=0;//Initialize the global share data; 15 /*Initializing the mutex lock*/ 16 if(pthread_mutex_init(&lock,NULL)!=0) 17 printf("Error intialializing the mutex lock\n"); 18 /*Creating a new thread*/ 19 if(pthread_create(&tid,NULL,thread,NULL)!=0) 20 printf("Error creating the thread\n"); 21 /*Waiting for the created thread to begin executing*/ 22 sleep(1); for(loop=0;loop<5;loop++) 25 { 26 /*Lock the mutex,update the data,unlock the mutex*/ 27 if(pthread_mutex_lock(&lock)!=0) 28 printf("Error locking the mutex\n"); 29 data++; 30 /*Dispaly the loop counter and update data value*/ 31 printf("Primary thread writing loop %d data %d\n",loop,data); 32 33 if(pthread_mutex_unlock(&lock)!=0) 34 printf("Error unlocking the mutex\n"); 35 36 sleep(1); 37 } 38 /*Waiting for the created thread to complete*/ 40 if(pthread_join(tid,NULL)!=0) 41 printf("Failed Join\n"); 42 printf("Primary Thread Stopped\n"); 43 44 return0; 45 } 46 47 void* thread(void* argument) 48 { 49 intloop;//loop counter; 50 printf("Created Thread Started ID %lu\n",pthread_self()); 51 sleep(1); 52 for(loop=0;loop<5;loop++) 53 { if(pthread_mutex_lock(&lock)!=0) 55 printf("Error locking mutex\n"); 56 data++; 57 58 printf("Creating thread writing loop %d data %d \n",loop,data); 59 if(pthread_mutex_unlock(&lock)!=0) 60 printf("Error unlocking the mutex\n"); 61 sleep(1); 62 } 63 64 printf("Creating Thread Stopped\n"); 65 return(NULL); 66 } 67
用gcc thread.c -lpthread 进行编译,注意,-lpthread要放在后面,不然会出现问题。
运行结果:
Primary Thread Started ID 3076118272 Created Thread Started ID 3076115264 Primary thread writing loop 0 data 1 Creating thread writing loop 0 data 2 Primary thread writing loop 1 data 3 Creating thread writing loop 1 data 4 Primary thread writing loop 2 data 5 Creating thread writing loop 2 data 6 Primary thread writing loop 3 data 7 Creating thread writing loop 3 data 8 Primary thread writing loop 4 data 9 Creating thread writing loop 4 data 10 Creating Thread Stopped Primary Thread Stopped