POSIX 线程库定义了线程属性对象 pthread_attr_t ,它封装了线程的创建者能够訪问和改动的线程属性。主要包含例如以下属性:

1. 作用域(scope)

2. 栈尺寸(stack size)

3. 栈地址(stack address)

4. 优先级(priority)

5. 分离的状态(detached state)

6. 调度策略和參数(scheduling policy and parameters)

线程属性对象能够与一个线程或多个线程相关联。当使用线程属性对象时。它是对线程和线程组行为的配置。使用属性对象的全部线程都将具有由属性对象所定义的全部属 性。尽管它们共享属性对象。但它们维护各自独立的线程 ID 和寄存器。

初始化/销毁线程属性

int pthread_attr_init(pthread_attr_t *attr);
int pthread_attr_destroy(pthread_attr_t *attr);

线程分离属性

int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

线程栈大小

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *stacksize);

普通情况下该值我们设置为0,使用系统默认设置的线程栈大小。否则可能会引起程序的可移植性的问题

线程栈溢出保护区大小

int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
int pthread_attr_getguardsize(pthread_attr_t *attr, size_t *guardsize);

guardsize意思是假设我们使用线程栈超过了设定大小之后,系统还会使用部分扩展内存来防止栈溢出。而这部分扩展内存大小就是guardsize. 只是假设自己改动了栈分配位置的话,那么这个选项失效,效果相当于将guardsize设置为0.

每一个线程都存在自己的堆栈。假设这些堆栈是相连的话,訪问超过自己的堆栈的话那么可能会改动到其它线程的堆栈。 假设我们设置了guardsize的话,线程堆栈会多开辟guarszie大小的内存,当訪问到这块内存时会触发SIGSEGV信号。

线程竞争范围(进程范围内的竞争 or 系统范围内的竞争)

int pthread_attr_getscope(const pthread_attr_t *attr,int *contentionscope);
int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope);

线程能够在两种竞争域内竞争资源:

1. 进程域(process scope):与同一进程内的其它线程

2. 系统域(system scope):与系统中的全部线程

作用域属性描写叙述特定线程将与哪些线程竞争资源。一个具有系统域的线程将与整个系 统中全部具有系统域的线程依照优先级竞争处理器资源,进行调度。

线程调度策略

int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);

进程的调度策略和优先级属于主线程,换句话说就是设置进程的调度策略和优先级仅仅 会影响主线程的调度策略和优先级。而不会改变对等线程的调度策略和优先级(注这句话不全然正确)。

每一个对等线程能够拥有它自己的独立于主线程的调度策略和优先级。

在 Linux 系统中,进程有三种调度策略:SCHED_FIFO(先进先出调度策略)、SCHED_RR(时间片轮转调度算法) 和 SCHED_OTHER(线程一旦開始执行,直到被抢占或者直到线程堵塞或停止为止)。线程也不例外。也具有这三种策略。

线程继承的调度策略

int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched);
int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);

在 pthread 库中,提供了一个函数,用来设置被创建的线程的调度属性:是从创建者线 程继承调度属性(调度策略和优先级),还是从属性对象设置调度属性。该函数就是:

int pthread_attr_setinheritsched (pthread_attr_t *   attr, int    inherit) 当中,inherit 的值为下列值中的其一:
enum
{
PTHREAD_INHERIT_SCHED, //线程调度属性从创建者线程继承
PTHREAD_EXPLICIT_SCHED //线程调度属性设置为 attr 设置的属性
};

假设在创建新的线程时,调用该函数将參数设置为 PTHREAD_INHERIT_SCHED 时,那么当改动进程的优先级时。该进程中继承这个优先级而且还没有改变其优先级的所 有线程也将会跟着改变优先级(也就是刚才那句话部分正确的原因)。

线程调度參数(实际上我们一般仅仅关心一个參数:线程的优先级,默觉得0)

int pthread_attr_getschedparam(const pthread_attr_t *attr, struct sched_param *param);
int pthread_attr_setschedparam(pthread_attr_t *attr, const struct sched_param *param);
//sched_param结构体
struct sched_param {
int sched_priority; /* Scheduling priority */
};

线程的并发级别

int pthread_setconcurrency(int new_level);
int pthread_getconcurrency(void);

说明:并发级别仅在N:M线程模型中有效。设置并发级别,给内核一个提示:表示提供给定级别数量的核心线程来映射用户线程是高效的(不过一个提示),默觉得0, 内核依照默认的方式进行并发。

我们来写一个样例来运用:

/** 查看线程默认属性 **/
void printThreadAttr()
{
pthread_attr_t attr;
pthread_attr_init(&attr); int detachstate;
pthread_attr_getdetachstate(&attr, &detachstate);
cout << "detach-state: "
<< (detachstate == PTHREAD_CREATE_JOINABLE ? "PTHREAD_CREATE_JOINABLE" : "PTHREAD_CREATE_DETACHED")
<< endl; size_t size;
pthread_attr_getstacksize(&attr, &size);
cout << "stack-size: " << size << endl; pthread_attr_getguardsize(&attr, &size);
cout << "guard-size: " << size << endl; int scope;
pthread_attr_getscope(&attr, &scope);
cout << "scope: "
<< (scope == PTHREAD_SCOPE_SYSTEM ?
"PTHREAD_SCOPE_SYSTEM" : "PTHREAD_SCOPE_PROCESS")
<< endl; int policy;
pthread_attr_getschedpolicy(&attr, &policy);
cout << "policy: ";
switch (policy)
{
case SCHED_FIFO:
cout << "SCHED_FIFO";
break;
case SCHED_RR:
cout << "SCHED_RR";
break;
case SCHED_OTHER:
cout << "SCHED_OTHER";
break;
default:
break;
}
cout << endl; int inheritsched;
pthread_attr_getinheritsched(&attr, &inheritsched);
cout << "inheritsched: "
<< (inheritsched == PTHREAD_INHERIT_SCHED ? "PTHREAD_INHERIT_SCHED" : "PTHREAD_INHERIT_SCHED")
<< endl; struct sched_param param;
pthread_attr_getschedparam(&attr, ¶m);
cout << "scheduling priority: " << param.sched_priority << endl;
cout << "concurrency: " << pthread_getconcurrency() << endl;
pthread_attr_destroy(&attr);
}

说明:

绑定属性:

Linux中採用“一对一”的线程机制。也就是一个用户线程相应一个内核线程。

绑定属性就是指一个用户线程固定地分配给一个内核线程。由于CPU时间片的调度是面向内核线程(也就是轻量级进程)的,因此具有绑定属性的线程能够保证在须要的时候总有一个内核线程与之相应。而与之相应的非绑定属性就是指用户线程和内核线程的关系不是始终固定的,而是由系统来控制分配的。

分离属性:

分离属性是用来决定一个线程以什么样的方式来终止自己。在非分离情况下,当一个线程结束时,它所占用的系统资源并没有被释放。也就是没有真正的终止。

仅仅有当pthread_join()函数返回时,创建的线程才干释放自己占用的系统资源。而在分离属性情况下,一个线程结束时马上释放它所占有的系统资源。这里要注意的一点是,假设设置一个线程的分离属性。而这个线程执行又非常快,那么它非常可能在pthread_create()函数返回之前就终止了。它终止以后就可能将线程号和系统资源移交给其它的线程使用。

Linux多线程实践(三)线程的基本属性设置API的更多相关文章

  1. Linux多线程实践(4) --线程特定数据

    线程特定数据 int pthread_key_create(pthread_key_t *key, void (*destr_function) (void *)); int pthread_key_ ...

  2. Linux多线程实践(2) --线程基本API

    POSIX线程库 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以"pthread_"开头,要使用这些函数库,要通过引入头文<pthread.h>,而且链 ...

  3. Linux多线程实践(1) --线程理论

    线程概念 在一个程序里的一个执行路线就叫做线程(thread).更准确的定义是:线程是"一个进程内部的控制序列/指令序列"; 一切进程至少有一个执行线程; 进程  VS. 线程  ...

  4. Linux多线程实践(3) --线程属性

    初始化/销毁线程属性 int pthread_attr_init(pthread_attr_t *attr); int pthread_attr_destroy(pthread_attr_t *att ...

  5. Linux多线程实践(9) --简单线程池的设计与实现

    线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收.所以 ...

  6. Linux多线程实践(一)线程基本概念和理论

    线程概念 在一个程序里的一个运行路线就叫做线程(thread).更准确的定义是:线程是"一个进程内部的控制序列/指令序列"; 对于每一个进程至少有一个运行线程; 进程  VS. 线 ...

  7. Linux多线程实践(四 )线程的特定数据

    在单线程程序中.我们常常要用到"全局变量"以实现多个函数间共享数据, 然而在多线程环境下.因为数据空间是共享的.因此全局变量也为全部线程所共同拥有.但有时应用程序设计中有必要提供线 ...

  8. Linux多线程实践(10) --使用 C++11 编写 Linux 多线程程序

    在这个多核时代,如何充分利用每个 CPU 内核是一个绕不开的话题,从需要为成千上万的用户同时提供服务的服务端应用程序,到需要同时打开十几个页面,每个页面都有几十上百个链接的 web 浏览器应用程序,从 ...

  9. 【Linux多线程】三个经典同步问题

    在了解了<同步与互斥的区别>之后,我们来看看几个经典的线程同步的例子.相信通过具体场景可以让我们学会分析和解决这类线程同步的问题,以便以后应用在实际的项目中. 一.生产者-消费者问题 问题 ...

随机推荐

  1. Could not load type 'System.ServiceModel.Activation.HttpModule' from assembly 'System.ServiceModel, Version=3.0.0.0,"解决办法

    这是因为先安装了 .NET Framework 4,随后启用了 .NET Framework 3.5 WCF HTTP 激活,则会发生此错误. 只需要已管理员用户在cmd中运行aspnet_regii ...

  2. VMware系统克隆

    第1章 搭建VMware实战环境 1.1 vmware主机配置-网络配置 1.1.1 虚拟主机添加网卡信息(5) a.右键虚拟主机→设置→添加虚拟网卡硬件设备 b.设置网络适配器类型→完成添加 1.1 ...

  3. robotframework自动化系列:新增流程

    刚接手项目的时候,要求所有流程在上线之前必须确保正向操作是正确的:这个时候又有新的模块需要测试,所以引入自动化测试是非常有必要的!通过对比,尝试使用RF进行自动化的回归测试. 测试中最常见的操作就是增 ...

  4. oracle精简客户端安装配置及常见问题

    有关Instant client 安装步骤 1.首先在官网下载两个安装包instant/sqlplus,对相关文件进行解压缩,存放本地路径 官网地址:http://www.oracle.com/tec ...

  5. 四:Java使用google的thumbnailator工具对图片压缩水印等做处理

    Thumbnailator是一个非常好的图片开源工具 使用方法: 在pom中加入以下jar包 <!-- 图片缩略图 图片压缩 水印 start--> <dependency>& ...

  6. boot之mybatis

    特别注意,此种方法和starter不兼容,我用了两个方式混蛋,发现跑不起来! spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driv ...

  7. PHP操作MySQL数据库之天龙八部 -- 七贱下天山 -- 六脉神剑

    天龙八部            八步操作数据库 七贱下天山        七步操作数据库  (将判断错误省略) 六脉神剑            六步操作数据库(将判断错误省略,将选择数据库添加到第一步 ...

  8. ligerUI---下拉菜单(menubar)动态显示(从后台获取数据)

    写在前面: ligerui的下拉菜单是有点丑的,这也是没有办法的事........这里主要记录下,如何从后台获取数据进行菜单显示. 有两种方式:1.使用json数组来动态添加  2.字符串拼接.  其 ...

  9. [最短路]P1828 香甜的黄油 Sweet Butter

    题目描述 农夫John发现做出全威斯康辛州最甜的黄油的方法:糖.把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油.当然,他将付出额外的费 ...

  10. 【原创】抓个Firefox的小辫子,围观群众有:Chrome、Edge、IE8-11

    前言 很多人都知道我们在做FineUI控件库,在这 9 年多的时间里,在和浏览器无数次的交往中,也发现了多个浏览器自身的BUG,并公开出来方便大家查阅: 分享IE7一个神奇的BUG(不是封闭标签的问题 ...