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

南昌网站网页设计百度seo优化工具

南昌网站网页设计,百度seo优化工具,凡科建站怎么保存网站,做门户网站要多少钱目录 1. Linux线程概念 什么是线程 线程的优点 线程的缺点 线程异常 线程用途 2. Linux进程VS线程 进程和线程 关于进程线程的问题 3. Linux线程控制 POSIX线程库 创建线程 线程ID及进程地址空间布局 线程终止 线程等待 为什么需要线程等待? 4. 分离线程 1. Linux线…

目录

1. Linux线程概念

什么是线程

线程的优点

线程的缺点

线程异常

线程用途

2. Linux进程VS线程

进程和线程

关于进程线程的问题

3. Linux线程控制

POSIX线程库

创建线程

线程ID及进程地址空间布局

线程终止

线程等待 为什么需要线程等待?

4. 分离线程


1. Linux线程概念

什么是线程

  • 在一个程序里的一个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”
  • 一切进程至少都有一个执行线程
  • 线程在进程内部运行,本质是在进程地址空间内运行
  • 在Linux系统中,在CPU眼中,看到的PCB都要比传统的进程更加轻量化
  • 透过进程虚拟地址空间,可以看到进程的大部分资源,将进程资源合理分配给每个执行流,就形成了线程执行流

线程的优点

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

线程的缺点

性能损失

  • 一个很少被外部事件阻塞的计算密集型线程往往无法与其它线程共享同一个处理器。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的 同步和调度开销,而可用的资源不变。

健壮性降低

  • 编写多线程需要更全面更深入的考虑,在一个多线程程序里,因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的,换句话说线程之间是缺乏保护的。

缺乏访问控制

  • 进程是访问控制的基本粒度,在一个线程中调用某些OS函数会对整个进程造成影响。

编程难度提高

  • 编写与调试一个多线程程序比单线程程序困难得多

线程异常

  • 单个线程如果出现除零,野指针问题导致线程崩溃,进程也会随着崩溃
  • 线程是进程的执行分支,线程出异常,就类似进程出异常,进而触发信号机制,终止进程,进程终止,该进程内的所有线程也就随即退出

线程用途

  • 合理的使用多线程,能提高CPU密集型程序的执行效率
  • 合理的使用多线程,能提高IO密集型程序的用户体验(如生活中我们一边写代码一边下载开发工具,就是多线程运行的一种表现)

2. Linux进程VS线程

进程和线程

  • 进程是资源分配的基本单位
  • 线程是调度的基本单位
  • 线程共享进程数据,但也拥有自己的一部分数据
  1. 线程ID
  2. 一组寄存器
  3. errno
  4. 信号屏蔽字
  5. 调度优先级

进程的多个线程共享同一地址空间,因此Text Segment、Data Segment都是共享的,如果定义一个函数,在各线程中都可以调用,如果定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:

  • 文件描述符表
  • 每种信号的处理方式(SIG_ IGN、SIG_ DFL或者自定义的信号处理函数)
  • 当前工作目录
  • 用户id和组id

进程和线程的关系如下图:

关于进程线程的问题

  • 如何看待之前学习的单进程?——具有一个线程执行流的进程

3. Linux线程控制

POSIX线程库

  • 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”开头的
  • 要使用这些函数库,要通过引入头文件<pthread.h>
  • 链接这些线程函数库时要使用编译器命令的“-lpthread”选项

创建线程

功能:创建一个新的线程
原型int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *
(*start_routine)(void*), void *arg);
参数thread:返回线程IDattr:设置线程的属性,attr为NULL表示使用默认属性start_routine:是个函数地址,线程启动后要执行的函数arg:传给线程启动函数的参数
返回值:成功返回0;失败返回错误码

错误检查:

  • 传统的一些函数是,成功返回0,失败返回-1,并且对全局变量errno赋值以指示错误。
  • pthreads函数出错时不会设置全局变量errno(而大部分其他POSIX函数会这样做)。而是将错误代码通过返回值返回
  • pthreads同样也提供了线程内的errno变量,以支持其它使用errno的代码。对于pthreads函数的错误, 建议通过返回值判定,因为读取返回值要比读取线程内的errno变量的开销更小
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
void *rout(void *arg) {int i;for( ; ; ) {printf("I'am thread 1\n");sleep(1);} 
}
int main()
{pthread_t tid;int ret = pthread_create(&tid, NULL, rout, NULL);if ( ret != 0 ) {fprintf(stderr, "pthread_create : %s\n", strerror(ret));exit(EXIT_FAILURE);}int i;for(; ; ) {printf("I'am main thread\n");sleep(1);}
}

线程ID及进程地址空间布局

  • pthread_ create函数会产生一个线程ID,存放在第一个参数指向的地址中。该线程ID和前面说的线程ID 不是一回事。
  • 前面讲的线程ID属于进程调度的范畴。因为线程是轻量级进程,是操作系统调度器的最小单位,所以需要 一个数值来唯一表示该线程。
  • pthread_ create函数第一个参数指向一个虚拟内存单元,该内存单元的地址即为新创建线程的线程ID, 属于NPTL线程库的范畴。线程库的后续操作,就是根据该线程ID来操作线程的。
  • 线程库NPTL提供了pthread_ self函数,可以获得线程自身的ID:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void* rout(void* arg) {int i;for ( ; ; ) {printf("I'm thread 1 virtualID: %lu\n", pthread_self());sleep(1);}// 建议添加返回值(虽然不会执行到这里)return NULL;
}int main() {pthread_t tid;int ret = pthread_create(&tid, NULL, rout, NULL);if (ret != 0) {perror("pthread_create failed");return 1;}for ( ; ; ) {printf("I'm main thread\n");sleep(1);}// 实际上不会执行到这里,需要更好的线程同步pthread_join(tid, NULL);return 0;
}

pthread_t 到底是什么类型呢?取决于实现。对于Linux目前实现的NPTL实现而言,pthread_t类型的线程ID,本质就是一个进程地址空间上的一个地址。

线程终止

如果需要只终止某个线程而不终止整个进程,可以有三种方法:

  1. 从线程函数return。这种方法对主线程不适用,从main函数return相当于调用exit。
  2. 线程可以调用pthread_ exit终止自己。
  3. 一个线程可以调用pthread_ cancel终止同一进程中的另一个线程。

pthread_exit函数

功能:线程终止
原型void pthread_exit(void *value_ptr);
参数value_ptr:value_ptr不要指向一个局部变量。
返回值:无返回值,跟进程一样,线程结束的时候无法返回到它的调用者(自身)

需要注意,pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是用malloc分配的,不能在线程函数的栈上分配,因为当其它线程得到这个返回指针时线程函数已经退出了。

pthread_cancel函数

功能:取消一个执行中的线程
原型int pthread_cancel(pthread_t thread);
参数thread:线程ID
返回值:成功返回0;失败返回错误码

线程等待 为什么需要线程等待?

  • 已经退出的线程,其空间没有被释放,仍然在进程的地址空间内。
  • 创建新的线程不会复用刚才退出线程的地址空间。

pthread_join函数

功能:等待线程结束
原型int pthread_join(pthread_t thread, void **value_ptr);
参数thread:线程IDvalue_ptr:它指向一个指针,指向线程的返回值
返回值:成功返回0;失败返回错误码

调用该函数的线程将挂起等待,直到id为thread的线程终止。thread线程以不同的方法终止,通过pthread_join得到的 终止状态是不同的,总结如下:

  1. 如果thread线程通过return返回,value_ ptr所指向的单元里存放的是thread线程函数的返回值。
  2. 如果thread线程被别的线程调用pthread_ cancel异常终掉,value_ ptr所指向的单元里存放的是常数 PTHREAD_ CANCELED。
  3. 如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数。
  4. 如果对thread线程的终止状态不感兴趣,可以传NULL给value_ ptr参数。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>void *thread1(void *arg)
{printf("thread 1 returning ... \n");int *p = (int*)malloc(sizeof(int));*p = 1;return (void*)p;
}void *thread2(void *arg)
{printf("thread 2 exiting ...\n");int *p = (int*)malloc(sizeof(int));*p = 2;pthread_exit((void*)p);
}void *thread3(void *arg)
{while (1) { // printf("thread 3 is running ...\n");sleep(1);}return NULL;
}int main(void)
{pthread_t tid;void *ret;// thread 1 returnpthread_create(&tid, NULL, thread1, NULL);pthread_join(tid, &ret);printf("thread return, thread id %lX, return code:%d\n", (unsigned long)tid, *(int*)ret);free(ret);// thread 2 exitpthread_create(&tid, NULL, thread2, NULL);pthread_join(tid, &ret);printf("thread return, thread id %lX, return code:%d\n", (unsigned long)tid, *(int*)ret);free(ret);// thread 3 cancel by otherpthread_create(&tid, NULL, thread3, NULL);sleep(3);pthread_cancel(tid);pthread_join(tid, &ret);if (ret == PTHREAD_CANCELED)printf("thread return, thread id %lX, return code:PTHREAD_CANCELED\n", (unsigned long)tid);elseprintf("thread return, thread id %lX, return code:NULL\n", (unsigned long)tid);
}

运行截图:

我们可以通过上面那个时间线的截图来帮助我们分析这段代码,这段代码首先有四个线程,三个分支线程一个主线程。我们让第一个分支线程执行:在堆上开辟一块空间,然后赋值并将其返回,第二个分支线程进行:同样的开空间赋值,多了一步终止线程pthread_exit函数,第三个分支是无限循环执行三秒,由外部调用pthread_cancle函数终止。

主线程就管理他们,并将他们的线程id和错误码打印出来我们可以观察到如上结果。

4. 分离线程

  • 默认情况下,新创建的线程是joinable的,线程退出后,需要对其进行pthread_join操作,否则无法释放资源,从而造成系统泄漏。
  • 如果不关心线程的返回值,join是一种负担,这个时候,我们可以告诉系统,当线程退出时,自动释放线程资源。
int pthread_detach(pthread_t thread);

可以是线程组内其他线程对目标线程进行分离,也可以是线程自己分离:

pthread_detach(pthread_self()); 

joinable和分离是冲突的,一个线程不能既是joinable又是分离的。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <unistd.h> 
#include <pthread.h> void *thread_run( void * arg ) 
{ pthread_detach(pthread_self()); printf("%s\n", (char*)arg); return NULL; 
} int main( void ) 
{ pthread_t tid; if ( pthread_create(&tid, NULL, thread_run, (void*)"thread1 run...") != 0 ) { printf("create thread error\n"); return 1; } int ret = 0; sleep(1);//很重要,要让线程先分离,再等待 if ( pthread_join(tid, NULL ) == 0 ) { printf("pthread wait success\n"); ret = 0; } else { printf("pthread wait failed\n"); ret = 1; } return ret; 
} 

由这段测试代码我们就可以得知分离后的线程,我们就不需要等待了。

http://www.dtcms.com/wzjs/210837.html

相关文章:

  • 南昌做网站公司有什么可以做推广的软件
  • 网站屏蔽复制seo深圳培训班
  • 一品威客网首页代做seo关键词排名
  • 响应式网站怎么做无缝轮播图网站设计公司苏州
  • 台州百度网站排名发帖推广
  • 网页打不开的原因及解决方法seo关键词排名优化费用
  • 功能网站开发网络营销工资一般多少
  • 建一个收费网站 怎么收费seo在线教学
  • 副业做网站程序网站手机优化
  • 有网站用nodejs做后台国内最新新闻
  • 英文网站推广方法代写软文
  • 做海报用的图片网站河源市seo点击排名软件价格
  • 网站开发模板免费下载seo内部优化具体做什么
  • 用jsp做视频网站百度网址安全中心怎么关闭
  • 网站seo怎样做网址查询入口
  • 为什么后台编辑内容和网站上面显示的内容不一致世界最新新闻
  • 眼查看网站开发语言绍兴seo排名公司
  • 中山公众号平台商场网站建设如何在百度上做广告宣传
  • 河南营销型网站建设如何做企业产品推广
  • 南宁市规划建设局 网站免费精准客源
  • 做网站必须要购买域名陕西网站推广公司
  • 网站建设一般怎么付款青岛seo排名公司
  • 网站排名软件下载windows清理优化大师
  • 做国际物流需要哪些网站2022最新引流推广平台
  • 建设网站西丽网络搜索优化
  • 昆山建设局图审中心网站北京网站优化策略
  • 阿里云建设网站流程搜索推广平台有哪些
  • 网站关键词如何优化网站设计公司建设网站
  • 网站能查到从哪里做的吗上海推广网络营销咨询热线
  • 网站进度条源代码juqery-ui网络推广引流有哪些渠道