#include<stdio.h>#include<pthread.h>#include<unistd.h>void* pthreadRun(void* arg){ int count = 3; while(count--) { printf("new pthread,tid:%lu,pid:%d/n",pthread_self(),getpid()); }}int main(){ pthread_t tid = 0; int ret = pthread_create(&tid,NULL,pthreadRun,NULL); if(ret != 0) { perror("pthread_create"); return -1; } if(ret != 0) { perror("pthread_detach"); return -1; } sleep(1); if(pthread_cancel(tid)!= 0) { printf("cancel failed/n"); return 1; } int exitCode; pthread_join(tid,(void**)&exitCode); printf("new pthread exit code:%d/n",exitCode); return 0;}这段程序的运行结果是:解释: 由于在主线程中已经sleep了1秒之后,才终止新线程的,由于在1秒之内,新线程早已运行完成,所以,就会终止失败。如果将终止新线程之前的sleep去掉,程序的运行结果究竟是什么呢?
解释:新线程没有执行完成,就被主线程终止了,此时是终止成功的,所以退出码就是-1.c.使用pthread_exit()自己终止自己。
(3)线程的等待:
(4)线程的可分离性: 一个线程是可结合的或者是可分离的。一个可结合的线程可以被与之在同一个进程中的其他线程所终止 ;而一个可分离的线程不需要主线程的等待,它的存储器等资源会在它运行结束时被操作系统回收。我们都知道,线程是进程内部的一个执行分支,为什么这么说?因为进程内的线程共享一个地址空间,所以在被分离的线程没有执行完成时,主线程不要退出,否则新的线程无法继续执行。主线程不可以等待被分离的线程。
程序举例:
#include<stdio.h>#include<pthread.h>#include<unistd.h>void* pthreadRun(void* arg){ int count = 3; while(count--) { printf("new pthread,tid:%lu,pid:%d/n",pthread_self(),getpid()); sleep(1); }}int main(){ pthread_t tid = 0; int ret = pthread_create(&tid,NULL,pthreadRun,NULL); if(ret != 0) { perror("pthread_create"); return -1; } usleep(1000); ret = pthread_detach(tid); if(ret != 0) { perror("pthread_detach"); return -1; } if(pthread_cancel(tid)!= 0) { printf("cancel failed/n"); return 1; } int exitCode; if(0 == pthread_join(tid,(void*)&exitCode)) { printf("wait success./n"); printf("new pthread exit code:%d/n",exitCode); } else { printf("wait failed/n"); } return 0;}程序运行结果:解释:从运行结果我们可以看出,我们不可以等待已经被分离的线程,但是可以终止已经分离的线程。(5)线程的切换:线程切换的条件: a.一个时间片的完成; b.操作系统模式的切换(内核态向用户态的切换)。时间片的结束,会进行线程的切换,这个是比较容易理解的。为什么操作系统模式的切换就会进行线程的切换?因为线程(在linux系统下,线程也被认为是进程,也有自己的PCB)的PCB是在内核中,只有内核态(也就是系统)才可以进行查看线程的信息,即就是访问PCB。我们知道,系统调用都是在内核态进行完成的,printf函数的底层调用的就是系统调用,所以我们采用printf函数进行显示数据的时候,就可能完成线程的切换。所以,写一个程序,制造线程的切换。
#include<stdio.h>#include<pthread.h>#include<unistd.h>static int count = 0;void* pthreadRun(void* arg){ int val = 0; int i = 0; while(i < 5000) { val = count; printf("new pthread,tid:%lu,pid:%d,count:%d/n",pthread_self(),getpid(),count); count = val + 1; i++; } return NULL;}int main(){ pthread_t tid1 = 0; pthread_t tid2 = 0; int ret = pthread_create(&tid1,NULL,pthreadRun,NULL); if(ret != 0) { perror("pthread_create"); return -1; } ret = pthread_create(&tid2,NULL,pthreadRun,NULL); if(ret != 0) { perror("pthread_create"); return -1; } pthread_join(tid1,NULL); pthread_join(tid2,NULL); printf("count:%d/n",count); return 0;}运行结果介于5000到10000之间不等。如果我们给临界资源加锁,运行完代码之后解锁。代码如下:#include<stdio.h>#include<pthread.h>#include<unistd.h>static int count = 0;pthread_mutex_t myLock = PTHREAD_MUTEX_INITIALIZER;void* pthreadRun(void* arg){ int val = 0; int i = 0; while(i < 3000) { pthread_mutex_lock(&myLock); val = count; printf("new pthread,tid:%lu,pid:%d,count:%d/n",pthread_self(),getpid(),count); count = val + 1; i++; pthread_mutex_unlock(&myLock); } return NULL;}int main(){ pthread_t tid1 = 0; pthread_t tid2 = 0; int ret = pthread_create(&tid1,NULL,pthreadRun,NULL); if(ret != 0) { perror("pthread_create"); return -1; } ret = pthread_create(&tid2,NULL,pthreadRun,NULL); if(ret != 0) { perror("pthread_create"); return -1; } pthread_join(tid1,NULL); pthread_join(tid2,NULL); pthread_mutex_destroy(&myLock); printf("count:%d/n",count); return 0;}这样对临界资源进行加锁之后,就可以保证全局变量最终可以加至6000.关于互斥锁的函数的声明:1)初始化和销毁函数2)申请和释放锁资源函数
为什么加锁就可以防止线程之间相互干扰? 那是因为加锁就可以保证锁之间的代码是一个原子操作(要么执行就能执行完,要么不执行,也就是非0即1的状态)。那么lock()和unlock()函数是如何实现的呢?方法一:
解释:我们知道mutex = 0;这一步并不是原子操作,如果两个线程同时调用lock函数,都判断出mutex > 0,然后其中一个线程将mutex置为0,另一个线程并不知道此事,也将mutex置为0,于是两个线程都以为自己获得了锁资源,这样就发生了冲突。所以这种办法是不可行的。执行赋值操作需要几步呢?步骤一:将mutex的数据从内存读到寄存器;步骤二:通过CPU内的运算器将mutex进行赋值;步骤三:将mutex的值重新写回内存。方法二:
解释:由于方法一中的赋值操作不是原子操作,导致上述方法不可取。为了解决这个问题,大多体系结构提供了swap或者exchange命令,将寄存器和内存里的值进行交换,就保证了原子操作。lock函数 语句解释:将al寄存器中的值放置为0;将al寄存器和内存中的mutex的值进行交换;......如果执行了xchgb指令之后,又有一个线程申请锁资源,此时它看到的mutex就是0,表示不可以申请到资源;如果执行了movb指令之后,又有一个线程申请锁资源,此时哪个线程获得锁资源,就看自己的优先级或者权限等等问题了。所以,这个方法就是lock函数和unlock函数里执行的操作了。关于线程的基本知识就先整理到这里~~
新闻热点
疑难解答