前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >UNIX(多线程):01---线程简介及线程限制

UNIX(多线程):01---线程简介及线程限制

作者头像
用户3479834
发布2021-02-03 14:25:55
7920
发布2021-02-03 14:25:55
举报
文章被收录于专栏:游戏开发司机

一、线程的概念

  • 典型的UNIX进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事。有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻能够做不止一件事,每个线程处理各自独立的任务

二、线程的优点

  • 通过为每种事件类型分配单独的处理线程,可以简化处理异步事件的代码。每个线程在进行事件处理时可以采用同步编程模式,同步编程模式要比异步编程模式简单得多
  • 同一进程多个线程可以自动的共享相同的存储地址空间和文件描述符
  • 有些问题可以分解从而提高整个程序的吞吐量。在只有一个控制线程的情况下,一个单线程进程要完成多个任务,只需要把这些任务串行化。但是有多个控制线程时,相互独立的任务的处理就可以交叉进行,此时只需要为每个任务分配一个单独的线程。当然只有在两个任务的处理过程相互不依赖的情况下,两个任务才可以交叉执行
  • 交互的程序同样可以通过多线程来改善响应事件,多线程可以把程序中处理用户输入输出的部分与其他部分分开

三、线程的其它特点

  • 有些人把多线程的程序设计与处理器或多核系统联系起来。但是即使程序运行在单处理器上,也能得到多线程编程模型的好处。处理器的数量并不影响程序结构,所以不管处理器的个数多少,程序都可以通过使用线程得以简化。而且,即使多线程程序在串行化任务时不得不阻塞,由于某些线程在阻塞时还有另一些线程可以运行,所以多线程在单处理器上运行还是可以改善响应时间和吞吐量
  • 每个线程都含有表示执行环境所必须的信息:其中包括进程中标识线程的线程ID, 一组寄存器值、栈、调度优先级和策略、信号屏蔽字、errno变量以及线程私有数据
  • 一个进程的所有信息对该进程的所有线程都是共享的:包括可执行代码、程序的全局内核和堆内存、栈以及文件描述符,因为它们共享同一存储区,所以各线程在访问共享数据时需要采取同步措施以避免不一致性

线程与进程的关系:

  • 在内核中没有线程这个概念,只有进程这个概念
  • 线程的实现与进程的实现很像,线程可以说是轻量级的进程,跟vfork有点像
  • 线程主要的问题是同步与互斥

备注(总结):

  • 不同线程中自己定义的数据,其他线程不能直接访问,是相互独立的
  • 只有全局变量,所有线程才能直接访问

四、线程的错误处理

  • 因为pthread_xxx系列函数在调用失败时并不设置errno,而是将错误编码通过函数返回。所以在线程函数的使用过程中,如果函数出错,应该获取其错误返回值(错误码)
  • 在线程中,从函数中返回错误码更为清晰整洁,不需要依赖那些随着函数执行不断变化的全局状态,这样可以吧错误的范围限制在引起出错的函数中

五、线程测试宏、常量(_POSIX_THREADS、_SC_THREADS)

下面文章讨论的线程接口来自POSIX.1-2001。线程接口也称为“pthread”或“POSIX线程”,原来在POSIX.1-2001中是一个可选功能,但是后来SUSv4把它们放入了基本功能

线程测试宏、常量:

  • POSIX线程的功能测试宏是_POSIX_THREADS:应用程序可以把这个宏用于#ifdef测试,从而在编译时确定是否支持线程
  • 也可以把_SC_THREADS常数用于调用sysconf函数:进而在运行时确定是否支持线程
  • 遵循SUSv4的系统定义符号_POSIX_THREADS的值为200809L

六、线程的系统限制

  • 可以使用sysconf函数测试下面的系统限制
  • 每个操作系统的限制的值如下:

七、线程的函数的出错返回

  • 线程的函数使用与其他函数不一样。线程函数失败时,返回错误编码。而不是错误编号(errno)

八、演示案例

  • 验证不同的线程之间自定义的数据,其他线程是不能直接访问的
代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>


void* func_thread_one(void* arg);
void* func_thread_two(void* arg);


int main()
{
pthread_t tid1,tid2;
int data=10;


//创建线程1
if(pthread_create(&tid1,NULL,func_thread_one,NULL)!=0){
perror("pthread_create");
exit(EXIT_FAILURE);
}
//创建线程2
if(pthread_create(&tid2,NULL,func_thread_two,NULL)!=0){
perror("pthread_create");
exit(EXIT_FAILURE);
}


sleep(2);
printf("Father running...\n");
printf("Father:data=%d\n",data);


if(pthread_join(tid1,NULL)!=0){
perror("pthread_join");
exit(EXIT_FAILURE);
}


if(pthread_join(tid2,NULL)!=0){
perror("pthread_join");
exit(EXIT_FAILURE);
}


exit(0);
}


void* func_thread_one(void* arg)
{
int data=66;
printf("thread1 running...\n");
printf("thread1:data=%d\n",data);
}


void* func_thread_two(void* arg)
{
int data=77;
printf("thread2 running...\n");
printf("thread2:data=%d\n",data);
}

附加:

  • 如果把子线程中定义的data都注释了,编译时将显示未定义的错误
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-12-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 游戏开发司机 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、线程的概念
  • 二、线程的优点
  • 三、线程的其它特点
  • 四、线程的错误处理
  • 五、线程测试宏、常量(_POSIX_THREADS、_SC_THREADS)
  • 六、线程的系统限制
  • 七、线程的函数的出错返回
  • 八、演示案例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档