当前位置: 首页 > news >正文

外贸淘宝网站建设智能网站建设软件有哪些

外贸淘宝网站建设,智能网站建设软件有哪些,百度推广整体优化网站,温州编程网站文章目录 多线程概念Linux下进程和线程的关系pid本质上是轻量级进程id#xff0c;换句话说#xff0c;就是线程IDLinux内核是如何创建一个线程的线程的共享和独有线程的优缺点 线程控制POSIX线程库线程创建线程终止线程等待线程分离 多线程概念 Linux下进程和线程的关系 在… 文章目录 多线程概念Linux下进程和线程的关系pid本质上是轻量级进程id换句话说就是线程IDLinux内核是如何创建一个线程的线程的共享和独有线程的优缺点 线程控制POSIX线程库线程创建线程终止线程等待线程分离 多线程概念 Linux下进程和线程的关系 在《程序员的自我修养》这本书中对Linux下的多线程做了这样的描述 Windows对进程和线程的实现如同教科书一样标准Windows内核有明确的线程和进程的概念。在Windows API可以使用明确的APICreateProcess和CreateThread来创建进程和线程并且有一系列的API来操纵它们。但对于Linux来说线程并不是一个通用的概念。 Linux对多线程的支持颇为贫乏事实上在Linux内核中并不存在真正意义上的线程的概念。 Linux将所有的执行实体无论是线程还是进程都称为任务Task每一个任务概念上都类似于一个单线程的进程具有内存空间、执行实体、文件资源等。不过Linux下不同的任务之间可以选择共享内存空间因而在实际意义上共享了同一个内存空间的多个任务构成了一个进程这些任务也就成了这个进程里的线程 可以给出以下结论 线程是依附于进程才能存在的如果没有进程则线程不会单独存在多线程的存在是为了提高整个程序的运行效率的线程也被称为执行流一个线程是执行代码的一个执行流因为线程在执行用户写的代码程序员创建的线程被称之为“工作线程”Linux内核当中没有线程的概念只有轻量级进程LWP线程是C库中的概念 pid本质上是轻量级进程id换句话说就是线程ID 在task_struct结构体当中 pid_t pid轻量级进程id也被称为线程id不同的线程拥有不用的pidpid_t tgid轻量级进程组id也被称为进程id一个进程当中的线程拥有相同的tgid 为什么在进程概念的介绍中说pid就是进程 id? 线程因为主线程的pid和tgid相等而我们当时进程中只有一个主线程。所以我们的pid就等于tgid。所以将pid成为进程id也就是现在的tgid。 Linux内核是如何创建一个线程的 其本质就是再在当前进程组中创建一个task_struct结构体它拥有着和主线程不同的pid指向同一块虚拟进程地址空间。 线程的共享和独有 独有 在进程虚拟地址空间的共享区当中调用栈寄存器 线程IDerrno信号屏蔽字 调度优先级独有 调用栈独享 寄存器独享 当操作系统调度进程的时候一定是以task_struct结构体调度而task _struc结构体是以双向链表存储而操作系统调度时是从就绪队列中调度已经就绪的进程在这里也就是轻量级进程-线程当调度时一定会有其他线程被切出而它切出时寄存器中存储的就是当前要执行的指令所以要用结构体中上下文信息保存 线程ID独享每个线程就是一个轻量级进程所以它有自己的pid errno独享当线程在执行出错时会返回一个errno这个errno属于当前自己的线程错误 信号屏蔽字独享阻塞位图 调度优先级独享每个进程/线程在执行时被调度的优先顺序 共享 共享文件描述符表用户id用户组id信号处理方式当前进程的工作目录 线程的优缺点 优先 多线程的程序拥有多个执行流合理使用要保证结果运行结构正确例如多个进程并发执行就可能会出现同时更改一块内存从而出现运行结果错误要控制线程的访问时序问题 可以提高程序的运行效率多线程程序的线程切换比多进程程序快付出的代价小 (因为这些线程指向同一个进程虚拟地址空间有些可以共享的数据比如全局变量就能在线程切换的时候不进行切换可以充分发挥多核CPU并行并行就是有多个CPU每个CPU执行一个线程各自执行各自的的优势计算密集型的程序可以进行拆分让不同的线程执行计算不一 样的事情比如我们要从1加到1亿我们可以让多个进程来各自计算其中一段加法可以更快的得出结果I/O密集型的程序可以进行拆分 让不同的线程执行不同的I/O操作可以不用串型运行 提高程序运行效率。比如我们要从多个文件中读取内容如果我们只有一个进程的话那就只能从一个文件中读取之后在从下一个文件中读取这样的串行运行但是当我们有多个进程就可以让多个进程从多个文件中同时读取。但也不是所有问题都可以拆分成多个进程去分开解决一个女人花十个月可以生出一个孩子但是十个女人不能再一个月生出一个孩子《程序员的自我修养》 再比如scanf是一个阻塞函数假如printf函数前面有scanf需要被执行这样在scanf没有完成的时候就不能往下执行printf但是我们让两个线程来分别来执行scanf和printf这样就不存在被scanf阻塞而后面的程序无法执行的问题了 缺点 编写代码的难度更加高当多个线程访问同一个程序的时候我们需要控制线程访问的先后顺序要不然就可能出现问题代码的(稳定性)鲁棒性要求更加高一个线程崩溃会导致整个进程退出。当多个线程在运行时而CPU资源少的情况下一定是有一线程访问不到CPU资源的那这时就一定要有线程被切换出来将CPU资源让出来这时一旦有线程霸占CPU资源占着不放的话此时这个得不到CPU资源的线程就有可能崩溃一旦它崩溃就会导致整个进程退出线程数量并不是越多越好线程的切换是需要时间的所以一个程序的线程数量一定是我们依照一个机器的配置CPU数量而经过测量来得出创建多少个线程合适 缺乏访问控制多个线程同时访问一个空间如果不加以控制可能会导致程序产生二义性结果 线程控制 POSIX线程库 线程相关的函数构成的函数库绝大多数函数是以pthread_开头的使用这些线程函数需要引入头文件pthread.h编译含有多线程函数的源文件时要加上编译命令-lpthread选项 线程创建 函数 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);参数 thread线程标识符是一个输出型参数本质上是线程独有空间的首地址attr线程的属性信息一般不设置属性信息传递NULL采用默认的线程属性如果要设置属性信息一般我们关心下列属性信息调用栈的大小、分离属性、调度策略、分时策略、调度优先级等等start_routine函数指针线程执行的入口函数线程执行起来的时候从该函数开始运行注意不是从main函数开始运行当前线程执行时都是从线程入口函数开始执行arg传递给线程入口函数的参数也就是给start_routine传递参数 返回值成功返回0失败返回0 线程创建代码演示 1 #includestdio.h2 #includeunistd.h3 #includepthread.h4 W 5 void* mythread_start(void* arg){6 printf(I am work thread\n); W 7 }8 9 int main(){10 pthread_t tid;11 int ret pthread_create(tid, NULL, mythread_start, NULL); 12 if(ret 0){13 perror(pthread_create);14 return 0;15 }16 return 0;17 } 注意在makefile文件中链接线程库 执行结果 很遗憾我们没看到应该存在的输出这是什么原因呢 因为线程都是需要操作系统进行调度的我们在main函数中创建出来一个线程但是我们的线程还没被调度main线程就执行结束返回了main函数返回就意味着进程结束了进程结束了我们的线程就不存在了自然不会再给出任何打印。 那我们想看到现象要怎么做呢很容易想到让main函数晚一点退出给工作线程充足的时间能被操作系统调度我们让main函数在返回前执行sleep(2) 再执行可以看到工作线程执行了它的代码 为了观察一下线程堆栈和函数堆栈我们索性让main函数和线程入口函数都进入睡眠状态修改后代码如下 1 #includestdio.h2 #includeunistd.h3 #includepthread.h4 W 5 void* mythread_start(void* arg){6 while(1){7 sleep(1);8 printf(I am work thread\n);9 }10 }11 12 int main(){13 pthread_t tid;14 int ret pthread_create(tid, NULL, mythread_start, NULL);15 if(ret 0){16 perror(pthread_create);17 return 0;18 }19 while(1){20 sleep(1); 21 }22 return 0;23 } 我们看看此时的调用堆栈 可以用top -H -p [pid]查看进程状态信息 我们试着给线程传递一下局部变量代码如下 1 #includestdio.h2 #includeunistd.h3 #includepthread.h4 5 void* mythread_start(void* arg){6 int* i (int*)arg;7 printf(I am work thread %d\n, *i); W 8 }9 10 int main(){11 pthread_t tid;12 for(int i0; i5; i){13 int ret pthread_create(tid, NULL, mythread_start, (void*)i); 14 if(ret 0){15 perror(pthread_create);16 return 0;17 }18 }19 sleep(1);20 return 0;21 } 观察一下程序执行结果 我们的预期是打印0-4的数字但是执行几次发现首先每次执行结果并不一样其次并不按照我们预期的结果进行打印这是怎么回事呢是因为线程是抢占式执行的可能是我们将所有的线程创建出来再去执行线程的代码或者说一边创建一边执行代码 线程的执行顺序不确定某个线程访问数据的时间也不确定导致了我们上述那么多种执行结果还有一种结果是访问数据5i是我们for循环种的局部变量如果for循环退出后还有线程去访问i这是十分危险的因为i已经被释放了此时再对它进行访问就有可能导致错误。 解决上面的方式有两种一种是在main函数中创建一个变量只要main函数存在其他那个变量就存在。而main函数退出线程也就退出了不存在非法访问。这种是解决非法访问的问题。 另一种方式是在堆上申请空间这样保证每个进程访问的数据是自己对应的数据 1 #includestdio.h2 #includeunistd.h3 #includepthread.h4 #includestdlib.h5 6 void* mythread_start(void* arg){7 int* p (int*)arg;8 printf(I am work thread%d\n, *p); 9 free(p); W 10 }11 12 int main(){13 pthread_t tid;14 for(int i0; i5; i){15 int *p (int*)malloc(sizeof(int));16 *p i;17 int ret pthread_create(tid, NULL, mythread_start, (void*)p);18 if(ret 0){19 perror(pthread_create);20 return 0;21 }22 }23 sleep(1);24 return 0;25 } 执行结果 总结 不要给线程传递临时变量因为传递临时变量当临时变量销毁时线程拿到的是临时变量的地址还可以访问那块被释放的空间容易造成进程崩溃线程入口函数传递参数的时候传递堆区空间释放堆区空间的时候让线程自己释放 线程终止 线程终止的方法 1、从线程入口函数种return返回 2、pthread_exit(void* retval)函数retval线程退出时 传递给等待线程的退出信息作用 谁调用谁退出主线程调用主线程终止工作线程调用工作线程终止 3、pthread_cancel(pthread_t)参数是一个线程标识符想要取消哪个线程就传递哪个线程的标识符 补充一个函数pthread_t pthread_self(void)返回调用此函数的线程id 代码演示 创建一个线程然后在main函数中终止这个线程为了防止是进程结束而导致线程也结束我们在main函数中加一个死循环 代码如下 1 #includestdio.h2 #includeunistd.h3 #includepthread.h4 W 5 void* pthread_start(void *arg){6 printf(I am work pthread\n);7 while(1){8 sleep(1);9 printf(I am work thread-l\n);10 }11 }12 int main(){13 pthread_t tid;14 int ret pthread_create(tid, NULL, pthread_start, NULL);15 if(ret 0){16 perror(pthread_create);17 return 0;18 }19 pthread_cancel(tid);20 while(1){21 sleep(1);22 printf(I am main pthread\n);23 }24 return 0;25 } 执行结果 能看到线程并没有立即终止而是执行了一下线程种的命令然后才终止 观察结束主线程而不结束工作线程会出现什么现象 代码如下 1 #includestdio.h2 #includeunistd.h3 #includepthread.h4 W 5 void* pthread_start(void *arg){6 printf(I am work pthread\n);7 while(1){ 8 sleep(1); 9 printf(I am work thread-l\n);10 } 11 } 12 int main(){ 13 pthread_t tid; 14 int ret pthread_create(tid, NULL, pthread_start, NULL);15 if(ret 0){ 16 perror(pthread_create); 17 return 0; 18 } 19 getchar();//设置阻塞当接受到字符后主线程将结束 20 pthread_cancel(pthread_self());//结束主线程 21 while(1){ 22 sleep(1); 23 printf(I am main pthread\n);24 } 25 return 0;26 } 设置阻塞的目的是为了查看进程id以观察进程 执行结果 getchar之前的状态 getchar之后的状态 用ps aux | grep tex查看前后对比 可以得出结论主线程先退出工作线程没退出主线程变成僵尸进程 验证pthread_cancle函数结束一个线程时它会执行下一行命令 代码思路将while循环去掉让线程退出的下一句代码是return 0观察程序状况 代码如下 2 #includeunistd.h3 #includepthread.h4 W 5 void* pthread_start(void *arg){6 printf(I am work pthread\n);7 while(1){8 sleep(1);9 printf(I am work thread-l\n);10 }11 }12 int main(){13 pthread_t tid;14 int ret pthread_create(tid, NULL, pthread_start, NULL);15 if(ret 0){16 perror(pthread_create);17 return 0;18 }19 getchar();//设置阻塞当接受到字符后主线程将结束20 pthread_cancel(pthread_self());//结束主线程21 //while(1){22 // sleep(1);23 // printf(I am main pthread\n);24 //} 25 return 0;26 }执行结果 可以发现这次进程直接退出了主线程也不是僵尸状态了这时因为当我们执行pthread_cancle函数时结束一个线程时他会执行下一行命令这时我们将主线程退出了它在退出前执行了return 0就会使得整个进程结束那么此时工作线程也就退出了 观察主线程先退出变成僵尸进程后工作线程执行完后主线程的状态 代码思路让主线程退出然后工作线程等待10s之后退出 代码如下 1 #includestdio.h2 #includeunistd.h3 #includepthread.h4 W 5 void* pthread_start(void *arg){6 int count 30;7 while(count--){8 sleep(1);9 printf(I am work thread-l\n);10 } W 11 }12 int main(){ 13 pthread_t tid;14 int ret pthread_create(tid, NULL, pthread_start, NULL);15 if(ret 0){16 perror(pthread_create);17 return 0;18 }19 //getchar();//设置阻塞当接受到字符后主线程将结束20 pthread_cancel(pthread_self());//结束主线程21 while(1){22 sleep(1);23 printf(I am main pthread\n);24 }25 return 0;26 } 执行结果分析 当主线程退出而工作线程不退出时我们是无法看到进程的调用栈信息的 总结 当我们执行pthread_cancle函数时结束一个线程时他会执行pthread_cancle函数下一行命令然后再结束线程当主线程退出后工作线程如果依然在执行主线程就会处于僵尸状态而当工作线程执行完毕之后退出整个进程也随之结束 线程等待 线程在创建出来的时候属性默认是joinable属性意味着线程在退出的时候需要其他执行流线程来回收线程的资源(主要是退出线程使用到的共享区当中的空间) 接口 int pthread_join(pthread_t thread, void **retval);功能若线程A调用了该函数等待B线程A线程会阻塞直到B线程退出后A线程才会解除阻塞状态 参数 pthread_t : 线程标识符要等待哪一个线程就传递哪个线程的标识符retval : 保存的是一个常数退出线程的退出信息 线程退出方式*retval保存的东西return入口函数返回值pthread_exit函数pthread_exit函数参数pthread_cancel函数PTHREAD_CANCEL宏定义 返回值成功返回0失败返回错误码 代码思路让工作线程等待30s退出然后在主线程中等待工作线程退出 代码如下 1 #includestdio.h2 #includeunistd.h3 #includepthread.h4 5 void* pthread_start(void *arg){6 int count 30;7 while(count--){8 sleep(1);9 printf(I am work thread-l\n);10 }11 }12 int main(){13 pthread_t tid;14 int ret pthread_create(tid, NULL, pthread_start, NULL);15 if(ret 0){16 perror(pthread_create);17 return 0;18 }19 pthread_join(tid, NULL); 20 return 0;21 } 执行分析 线程分离 分离线程是将线程标记成已分离其属性从joinable变成detach对于detach属性的线程终止后系统会自动回收其资源不用任何线程回收其资源 接口 int pthread_detach(pthread_t thread);功能将线程标记为已分离目的是当分离的线程终止时其资源会自动释放防止产生僵尸进程防止内存泄漏 参数pthread_t需要标记分离的线程标识符 调用pthread_detach函数的位置可以是 在主线程中调用分离创建出来的线程即主线程标记分离工作线程在工作线程的线程入口函数中调用即自己标记分离自己; 线程分离的实质就是将线程的属性设置为detach工作线程退出然后不回收它的退出状态信息 代码如下 1 #includestdio.h2 #includeunistd.h3 #includepthread.h4 W 5 void* pthread_start(void *arg){6 int count 10;7 while(count--){8 sleep(1);9 printf(I am work thread-l\n);10 } W 11 }12 int main(){13 pthread_t tid;14 int ret pthread_create(tid, NULL, pthread_start, NULL);15 if(ret 0){16 perror(pthread_create);17 return 0;18 }19 //pthread_join(tid, NULL);20 while(1){21 sleep(1);22 }23 return 0;24 }执行结果分析 可以看到它运行完直接退出了也没有变成僵尸状态 将工作线程设置为分离状态观察 代码如下 1 #includestdio.h2 #includeunistd.h3 #includepthread.h4 W 5 void* pthread_start(void *arg){6 pthread_detach(pthread_self()); 7 int count 30;8 while(count--){9 sleep(1);10 printf(I am work thread-l\n);11 } W 12 }13 int main(){14 pthread_t tid;15 int ret pthread_create(tid, NULL, pthread_start, NULL);16 if(ret 0){17 perror(pthread_create);18 return 0;19 }20 //pthread_join(tid, NULL);21 while(1){22 sleep(1);23 }24 return 0;25 } 执行分析 结论无论其他线程等待不等待工作线程退出回收它的退出状态信息工作线程都不会变为僵尸状态。
http://www.dnsts.com.cn/news/60310.html

相关文章:

  • wordpress你访问的网站不存在wordpress 我爱水煮鱼
  • 南宁网站建设找哪家好苏州知名网站建设建站公司
  • 公司网站一般用什么软件做做任务送科比网站
  • 酒业公司网站模板wordpress主题在线检测工具
  • 怎么做不花钱的网站做黑彩网站赚钱吗
  • 招商银行官网首页 网站餐饮logo免费设计
  • 个人网站建设大全厦门做网站推广
  • 海南省交通建设局网站东莞市保安公司排名
  • 定制公司网站软件开发就业前景走向
  • 网站制作的服务商wordpress 文章发布失败
  • 包头网站建设设计网络优化公司哪家好
  • 做网站堵怕犯法吗政务网站建设办法
  • php做网站需要啥技术网站费用构成
  • 网页设计怎么建立网站化妆品网站建设说明
  • 做网站优化的好处网站制作哪家好
  • 正在运营的网站被注销备案怎么办南京seo关键词排名
  • 商城网站数据库编写网站程序
  • 做网站哪种编程语言好wordpress伪静态规则
  • 沈阳网站推广排名方案网站开发记什么科目
  • 南京网站优化公司排名青锐成长计划网站开发过程
  • 建设网站需要多少钱搭建一个小程序需要多少钱
  • vps网站如何设置缓存短视频推广策划方案模板
  • 网站建设步骤列表图片手机网站制作优化
  • 公司如何登录网站做就业登记虚拟主机 域名 和网站关系
  • 清溪仿做网站wordpress4.9.5
  • 沈阳网站维护南昌百度快速排名提升
  • 网站开发培训那个好价格查询
  • 广州互邦物流网络优化建站做网站教程
  • wordpress rpc长沙网站seo诊断
  • 做一个网站的市场价北京app开发公司官网