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

苏州做网站的单位/五种营销工具

苏州做网站的单位,五种营销工具,wordpress icp备案号,东莞排名seo网站关键词优化程序的一个执行路线就叫做线程,线程是一个进程内部的一个控制序列。一个进程至少有一个线程。 我们通过一幅图来了解下一线程和进程的关系 我们通过图片可以清楚的理解为什么说线程是程序的一个执行路线。线程又被称作是轻量级进程。 那么我们可以理解&#xff0c…

程序的一个执行路线就叫做线程,线程是一个进程内部的一个控制序列。一个进程至少有一个线程。

我们通过一幅图来了解下一线程和进程的关系

我们通过图片可以清楚的理解为什么说线程是程序的一个执行路线。线程又被称作是轻量级进程。

那么我们可以理解,在一个进程下,多个线程之间的很多资源是共享的,比如地址空间(包括代码段,数据段,如果定义一个函数或者全局变量,在各个线程都可以调用)。除此之外还共享以下资源:文件描述符表、信号处理方式、用户ID和组ID、和当前工作目录。线程也拥有自己的数据,比如:寄存器、栈、线程ID、调度优先级、errno。

线程是执行程序的最小单位,进程是资源竞争的基本单位。

线程的优缺点:

     1. 创建一个新线程的代价要⽐创建一个新进程⼩得多
     2. 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多 (因为一个进程的多个线程共享地址空间)
     3. 线程占用的资源要比进程少很多
     4. 能充分利用多处理器的可并行数量 
     5. 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
     6. 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现 
     7. I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作

线程的缺点:
     1. 一些系统调用及异常都是针对整个线程,因此若一个线程出问题,整个进程都会受到影响
     2. 线程的安全性较低
     3. 因为共享了数据,通信变的方便,但是资源的争抢就会体现出来因此编码难度要更高一点

创建线程:
函数原型:int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*star t_routine)(void*), void *arg); 
        thread:返回线程id
        attr:设置线程的属性 ,attr为NULL表⽰示使⽤用默认属性 
        star t_routine:是个函数地址,线程启动后要执行的函数,函数退出了,线程也就退出了
        arg:传给线程启动函数的参数
        返回值:成功返回0,失败返回错误码。
传统的一些函数在错诶时会将错误码放在errno中,但该函数出错时不会设全局变量errno,而是将错误码作为返回值返回。

线程ID:

1. 在Linux中,目前的线程实现是Native POSIX Thread Libaray 简称NPTL。在这种实现下,线程又被称为轻量级进程,每一个用户态的线程,在内核中都对应一个调度实体,也拥有自己的进程描述符(task_struct结构体)。
2. 没有线程之前,一个进程对应内核里的一个进程描述符,对应一个进程ID。但是引入线程概念之后,情况发生了变化,一个用户进程下管辖N个用户态线程,每个线程作为一个独立的调度实体在内核态都有自己的进程描述符,进程和内核的描述符一下子就变成了 1:N关系,POSIX标准又要求进程内的所有线程调用 getpid 函数时返回相同的进程ID,如何解决上述问题呢?
3. Linux内核引入了线程组的概念。

我们可以先查看一下task_struct结构:
 

struct task_struct {...pid_t pid;pid_t tgid;...struct task_struct *group_leader;...struct list_head thread_group;...
};

多线程的进程可以看成是一个线程组。我们可以看到结构体中有一个pid,看起来这是我们的进程ID,其实不是,这个pid实际上是线程ID;而tgid(Thread Group ID)对应的则是用户态下的进程ID。所以我们用gitpid()函数得到的是tgid,即进程ID。而我们的线程ID,即pid(结构体中),可以通过gittid()函数来获得。
我们可以通过命令ps -eL来查看线程信息(LWP线程ID)

接下来我们看一段代码:
 

#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>void *thread_run1(void* arg)
{while(1){sleep(1);}   
}
void *thread_run2(void *arg)
{while(1){sleep(1);}
}
int main()
{pthread_t tid1;pthread_t tid2;pthread_create(&tid1,NULL,thread_run,NULL);pthread_create(&tid2,NULL,thread_run2,NULL);
}

运行该程序并用ps -eL命令查看


我们可以看到有一个线程的线程id和进程id一样,这是为什么呢?
线程组内的第⼀个线程,在⽤户态被称为主线程(main thread),在内核中被称为group leader,内核在创建
第⼀个线程时,会将线程组的ID的值设置成第⼀个线程的线程ID,group_leader指针则指向⾃⾝,
既主线程的进程描述符。所以线程组内存在⼀个线程ID等于进程ID,⽽该线程即为线程组的主线
程。
我们都知道,线程ID是pid_t类型的,但是我们创建线程的函数pthread_create会创建一个线程id并把它放到第一个参数指向的地址中。这个线程id是pthread_t类型,和之前讲到的pid_t类型不是一回事,这个线程id使我们用户看到的id,可以通过这个线程id来对线程进行其他库函数操作。该线程id可以通过函数 pthread_t pthread_self(void)来获得,而且pthread_t类型本质是一个地址,可以用%p打印。

线程终止:

如果只终止一个线程而不终止进程,我们有三种方法。
1.在线程函数中return。
2.线程调用函数  void pthread_exit(void** value_ptr);
3.一个线程可以调用pthread_cancel终止同一进程中的另一个线程。

从线程函数return从而退出线程这种方式不适用于主线程。
void pthread_exit(void** value_ptr) 该参数指向一个非局部变量(后面详细说明)。该函数没有返回值,因为线程退出后无法返回到它的调用者。
调用int pthread_cancel(pthread_t thread) 成功返回0,失败返回错误码。给线程发送一个终止信号。调用该函数时,最好用pthread_join函数(下面介绍)来等待线程的退出,否则可能会出现段错误。

线程等待:

如果一个线程退出但其空间没有释放,仍然在进程的地址空间内,这样就会发生内存泄漏问题,创建新的线程不会复用刚才退出的地址空间。类似进程等待函数waitpid。线程等待也有一个函数。
int pthread_join(pthread_t thread,void **value_ptr);
调用该函数的线程将挂起等待,直到id为thread的线程终止。线程以不同方式终止,通过该函数得到的终止状态是不同的。终止状态体现在第二个参数value_ptr中。
1.通过线程函数return来终止线程,value_ptr中存放的值是线程函数返回的值。
2.通过pthread_exit来终止线程,value_ptr中存放的是pthread_exit函数的参数。所以这就是为什么pthread_exit函数中的参数只能是全局数据或者从堆上动态分配的数据,而不能是线程函数栈上的数据,因为线程函数退出后,其局部变量也释放掉。
3.通过pthread_cancel函数来终止另一个线程,value_ptr所指向的单元存放的是常数PTHREAD_CANCELED(-1)。
如果对线程退出状态不关心可以将参数设置为NULL。
我们通过代码来验证:

#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
#include<malloc.h>void* thread_run1(void *arg)
{int *p=(int*)malloc(sizeof(int));*p=100;sleep(1);printf("thread_run1  id:%p\n",pthread_self());return (void*)p;
}
void* thread_run2(void *arg)
{while(1){sleep(1);printf("thread_run2  id:%p\n",pthread_self());int *p=(int*)malloc(sizeof(int));*p=200;pthread_exit((void*)p);}
}
void* thread_run3(void *arg)
{while(1){sleep(1);printf("thread_run3  id:%p\n",pthread_self());}return NULL;
}
int main()
{void *ret;pthread_t tid1,tid2,tid3;pthread_create(&tid1,NULL,thread_run1,NULL);pthread_join(tid1,&ret);printf("%d\n",*(int*)ret);sleep(1);pthread_create(&tid2,NULL,thread_run2,NULL);pthread_join(tid2,&ret);printf("%d\n",*(int*)ret);sleep(1);pthread_create(&tid3,NULL,thread_run3,NULL);sleep(2);pthread_cancel(tid3);pthread_join(tid3,ret); //注意这里给第二个参数的时候就不要取地址了,因为要保存的是常数-1,否则会发生段错误。printf("%d\n",*(int*)ret);return 0;
}

程序运行结果如下:

线程分离:

默认情况下,新创建的线程是joinable的,线程退出后,需要对其进⾏pthread_join操作,否则⽆法释放资源,从⽽造成系统泄漏。我们可以将线程设置为分离的,这样在线程退出后会自动释放线程资源。
int pthread_detach(pthread_t thread);
joinable和分离是冲突的,⼀个 线程不能既是joinable⼜是分离的。

http://www.lbrq.cn/news/2248507.html

相关文章:

  • 做公司网站需要多久/seo在线优化平台
  • 个人建站哪类站赚钱/北京优化网站公司
  • 成都模板网站建设服务/网页设计与制作用什么软件
  • 做网站去哪里接单/企业自建网站
  • wordpress文章页不显示侧边/班级优化大师
  • 教学网站开发应用指导方案/网站建设公司seo关键词
  • 网站开发原型法/steam交易链接怎么用
  • 网站建设的认可/重庆森林经典台词
  • 虎门专业做网站/百度官方电话
  • 网站建设规划设计/信息流广告哪个平台好
  • 哪个网站有老外教做蛋糕/360收录查询
  • 腾讯云怎么建网站/做网站建网站公司
  • 南山做网站公司/小程序排名优化
  • 做微信网站公司名称/厦门seo外包服务
  • 教师在哪些网站可以做兼职/南昌seo报价
  • 揭阳seo网站管理/优秀营销软文范例100字
  • php怎样做网站/网络营销模式包括哪些
  • paypal网站做外贸/绍兴百度seo排名
  • 电子书新手学做网站/百度搜索指数排名
  • wordpress用thinkphp/搜索引擎优化人员优化
  • 建站行业市场分析/新产品推广方式有哪些
  • 石家庄做网站建设的公司哪家好/关键词优化靠谱推荐
  • 达州市网站建设/网络营销环境分析主要包括
  • 竞价网站做推广方案/市场营销经典案例
  • 代做网页设计作业/百度关键词seo排名
  • 做图软件下载官方网站/怎么推广公众号让人关注
  • 营销型网站的优势/网络推广工作
  • 网站开发推荐书籍/微信推广费用一般多少
  • 炒币网站开发/百度平台交易
  • 在猪八戒上做网站要注意什么/百度上海分公司地址
  • OpenCV稠密光流估计的一个类cv::optflow::DenseRLOFOpticalFlow
  • rustdesk远控电脑替代todesk,平替向日葵等软件
  • 小型客厅如何装修设计?
  • 基于多智能体强化学习的医疗检索增强生成系统研究—MMOA-RAG架构设计与实现
  • OFDM系统中关于信号同步的STO估计与CFO估计的MATLAB仿真
  • FreeRTOS之链表操作相关接口