POSIX线程(二)

一. 线程属性

(1) 初始化与销毁属性

int pthread_attr_init(pthread_attr_t *attr);

int pthread_attr_destroy(pthread_attr_t *attr);

(2)获取与设置分离属性

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);

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

(3) 获取与设置栈大小

int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);

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

(4)获取与设置栈溢出保护区大小

int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);

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

(5) 获取与设置线程在竞争范围

int pthread_attr_setscope(pthread_attr_t *attr, int scope);

int pthread_attr_getscope(pthread_attr_t *attr, int *scope);

(6) 获取与设置调度策略

int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);

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

(7)获取与设置继承的调度策略

int pthread_attr_setinheritsched(pthread_attr_t *attr,

int inheritsched);

int pthread_attr_getinheritsched(pthread_attr_t *attr,

int *inheritsched);

(8) 获取与设置调度参数

int pthread_attr_setschedparam(pthread_attr_t *attr,

const struct sched_param *param);

int pthread_attr_getschedparam(pthread_attr_t *attr,

struct sched_param *param);

(9) 获取与设置并发级别

int pthread_setconcurrency(int new_level);

int pthread_getconcurrency(void);

    仅仅在N:线程模型中有效,设置并发级别,给内核一个提示: 表示提供给定级别数量的核心线程来映射用户线程是高效的.

#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#define ERR_EXIT(m)         do         {                 perror(m);                 exit(EXIT_FAILURE);         } while(0)

int main(void)
{
    pthread_attr_t attr;
    pthread_attr_init(&attr);

	//获取与设置分离属性
    int state;
    pthread_attr_getdetachstate(&attr, &state);
    if (state == PTHREAD_CREATE_JOINABLE)
        printf("detachstate:PTHREAD_CREATE_JOINABLE\n");
    else if (state == PTHREAD_CREATE_DETACHED)
        printf("detachstate:PTHREAD_CREATE_DETACHED");

	// 获得栈大小
    size_t size;
    pthread_attr_getstacksize(&attr, &size);
    printf("stacksize:%d\n", size);

	// 获取与设置栈溢出保护区大小
    pthread_attr_getguardsize(&attr, &size);
    printf("guardsize:%d\n", size);

	//获取与设置线程在竞争范围
    int scope;
    pthread_attr_getscope(&attr, &scope);
    if (scope == PTHREAD_SCOPE_PROCESS)
        printf("scope:PTHREAD_SCOPE_PROCESS\n");
    if (scope == PTHREAD_SCOPE_SYSTEM)
        printf("scope:PTHREAD_SCOPE_SYSTEM\n");

	// 获取与设置调度策略
    int policy;
    pthread_attr_getschedpolicy(&attr, &policy);
    if (policy == SCHED_FIFO)
        printf("policy:SCHED_FIFO\n");
    else if (policy == SCHED_RR)
        printf("policy:SCHED_RR\n");
    else if (policy == SCHED_OTHER)
        printf("policy:SCHED_OTHER\n");

	// 获取与设置继承的调度策略
    int inheritsched;
    pthread_attr_getinheritsched(&attr, &inheritsched);
    if (inheritsched == PTHREAD_INHERIT_SCHED)
        printf("inheritsched:PTHREAD_INHERIT_SCHED\n"); // 继承调用线程属性
    else if (inheritsched == PTHREAD_EXPLICIT_SCHED)
        printf("inheritsched:PTHREAD_EXPLICIT_SCHED\n"); // 需要自己设置

	// 获取与设置调度参数
    struct sched_param param;
    pthread_attr_getschedparam(&attr, ¶m);
    printf("sched_priority:%d\n", param.sched_priority);

    pthread_attr_destroy(&attr);

    return 0;
}

二. 线程特定数据

(1)在单线程程序中,经常用到"全局变量"以实现多个函数间共享数据.

(2)在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有.

(3)但有时应用程序设计中有必要提供线程私有的全局变量,仅仅在某个线程中有效,但却可以跨多个函数访问.

    (4)POSIX线程库通过维护一定的数据结构来解决这个问题,这些数据结构称为(TSD).

线程特定数据存在的意义

现在有一全局变量,所有线程都可以使用它,改变它的值。而如果每个线程希望能单独拥有它,那么就需要使用线程存储了。表面上看起来这是一个全局变量,所有线程都可以使用它,而它的值在每一个线程中又是单独存储的。这就是线程存储的意义。

1. 创建一个类型为 pthread_key_t 类型的变量。

2. 调用 pthread_key_create() 来创建该变量。该函数有两个参数,第一个参数就是上面声明的 pthread_key_t 变量,第二个参数是一个清理函数,用来在线程释放该线程存储的时候被调用。该函数指针可以设成 NULL ,这样系统将调用默认的清理函数。

3. 当线程中需要存储特殊值的时候,可以调用 pthread_setspcific() 。该函数有两个参数,第一个为前面声明的 pthread_key_t 变量,第二个为 void* 变量,这样你可以存储任何类型的值。

4. 如果需要取出所存储的值,调用 pthread_getspecific() 。该函数的参数为前面提到的 pthread_key_t 变量,该函数返回 void * 类型的值。

当调用pthread_key_create 后会产生一个所有线程都可见的线程特定数据(TSD)的pthread_key_t 值,调用,虽然只有一个pthread_key_t,但每个线程的特定数据是独立的内存空间,当线程退出时会执行destructor 函数.

相关函数:

    int pthread_key_create(pthread_key_t *key, void (*destructor)(void*));

int pthread_key_delete(pthread_key_t key);

void *pthread_getspecific(pthread_key_t key);

int pthread_setspecific(pthread_key_t key, const void *value);

int pthread_once(pthread_once_t *once_control,

void (*init_routine)(void));

pthread_once_t once_control = PTHREAD_ONCE_INIT;

tsd.c

#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#define ERR_EXIT(m)         do         {                 perror(m);                 exit(EXIT_FAILURE);         } while(0)

typedef struct tsd
{
    pthread_t tid;
    char *str;
} tsd_t;

pthread_key_t key_tsd;

pthread_once_t once_control = PTHREAD_ONCE_INIT;

void destroy_routine(void *value)
{
    printf("destory ...\n");
    free(value);
}

void once_routine(void)
{
    pthread_key_create(&key_tsd, destroy_routine);
    printf("key init ...\n");
}

void *thread_routine(void *arg)
{
	//pthread_key_create(&key_tsd,destroy_routine);
    //pthread_once(&once_control, once_routine); //保证once_routine只会调用一次
    // 使用malloc分配内存
    tsd_t *value = (tsd_t *)malloc(sizeof(tsd_t));
    value->tid = pthread_self(); // 填值ID
    value->str = (char *)arg;// 传递的字符串

	//pthread_setspecific 后会将每个线程的特定数据与pthread_key_t 绑定起来
    pthread_setspecific(key_tsd, value);
    printf("%s setspecific ptr=%p\n", (char *)arg, value);
    // 获取特定值
    value = pthread_getspecific(key_tsd);
    printf("tid=0x%x str=%s ptr=%p\n", (int)value->tid, value->str, value);
    sleep(2);
    // 获取特定值
    value = pthread_getspecific(key_tsd);
    printf("tid=0x%x str=%s ptr=%p\n", (int)value->tid, value->str, value);
    return NULL;
}

int main(void)
{
	//当调用pthread_key_create 后会产生一个所有线程都可见的线程特定数据(TSD)的pthread_key_t 值
   	pthread_key_create(&key_tsd, destroy_routine);
    pthread_t tid1;
    pthread_t tid2;
    // 创建两个线程
    pthread_create(&tid1, NULL, thread_routine, "thread1");
    pthread_create(&tid2, NULL, thread_routine, "thread2");

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);

    pthread_key_delete(key_tsd);
    return 0;
}

把64,42,43行的注释去掉,只有一个第一个进入的线程调用once_routine

时间: 2024-08-27 21:55:33

POSIX线程(二)的相关文章

POSIX 线程编程(二)线程建立与终止

创建与终止线程 线程的管理常用的API有:pthread_create(thread,attr,start_routine,arg) pthread_exit(status) pthread_cancel(thread) pthread_attr_init(attr) pthread_attr_destroy(attr) 创建线程: 一个main程序包含一个默认的主线程,这个主线程在程序开始运行的时候由系统创建.除此之外的所有其他线程必须由程序员显式的创建. pthread_create 创建一

POSIX 线程详解(经典必看)

总共三部分: 第一部分:POSIX 线程详解                                   Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  2000 年 7 月 01 日 第二部分:通用线程:POSIX 线程详解,第 2部分       Daniel Robbins ([email protected]), 总裁/CEO, Gentoo Technologies, Inc.  20

POSIX 线程详解(2-线程创建和销毁)

算法旨在用尽可能简单的思路解决问题,理解算法也应该是一个越看越简单的过程,当你看到算法里的一串概念,或者一大坨代码,第一感觉是复杂,此时不妨从例子入手,通过一个简单的例子,并编程实现,这个过程其实就可以理解清楚算法里的最重要的思想,之后扩展,对算法的引理或者更复杂的情况,对算法进行改进.最后,再考虑时间和空间复杂度的问题. 了解这个算法是源于在Network Alignment问题中,图论算法用得比较多,而对于alignment,特别是pairwise alignment, 又经常遇到maxim

POSIX 线程(一)

一. POSIX线程先关函数 POSIX线程库 与线程有关的函数构成一个完整的系列,绝大多数函数的名字都是以"pthread"打头的 要使用这些函数库,引入头文件<pthread.h> 连接这些线程函数库时要使用编译器命令的"-lpthread"选项 1. pthread_create函数 功能:创建一个新的线程 原型: int pthread_create(pthread_t *thread, const pthread_attr_t *attr, v

Posix线程编程指南(2)

Posix线程编程指南(2) 杨沙洲 原文地址:http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part2/ 线程私有数据 这是一个关于Posix线程编程的专栏.作者在阐明概念的基础上,将向您详细讲述Posix线程库API.本文是第二篇将向您讲述线程的私有数据. 概念及作用 在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据.在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程

posix 线程(一):线程模型、pthread 系列函数 和 简单多线程服务器端程序

posix 线程(一):线程模型.pthread 系列函数 和 简单多线程服务器端程序 一.线程有3种模型,分别是N:1用户线程模型,1:1核心线程模型和N:M混合线程模型,posix thread属于1:1模型. (一).N:1用户线程模型 “线程实现”建立在“进程控制”机制之上,由用户空间的程序库来管理.OS内核完全不知道线程信息.这些线程称为用户空间线程.这些线程都工作在“进 程竞争范围”(process contention scope):各个线程在同一进程竞争“被调度的CPU时间”(但

转载:Posix线程编程指南(2)

概念及作用 在单线程程序中,我们经常要用到"全局变量"以实现多个函数间共享数据.在多线程环境下,由于数据空间是共享的,因此全局变量也为所有线程所共有.但有时应用程序设计中有必要提供线程私有的全局变量,仅在某个线程中有效,但却可以跨多个函数访问,比如程序可能需要每个线程维护一个链表,而使用相同的函数操作,最简单的办法就是使用同名而不同变量地址的线程相关数据结构.这样的数据结构可以由Posix线程库维护,称为线程私有数据(Thread-specific Data,或TSD). 回页首 创建

POSIX 线程详解(1-概述)

线程是有趣的 线程类似于进程.如同进程,线程由内核按时间分片进行管理.在单处理器系统中,内核使用时间分片来模拟线程的并发执行,这种方式和进程的相同.而在多处理器系统中,如同多个进程,线程实际上一样可以并发执行. 那么为什么对于大多数合作性任务,多线程比多个独立的进程更优越呢?这是因为,线程共享相同的内存空间.不同的线程可以存取内存中的同一个变量.所以,程序中的所有线程都可以读或写声明过的全局变量.如果曾用 fork() 编写过重要代码,就会认识到这个工具的重要性.为什么呢?虽然 fork() 允

POSIX线程(1)

POSIX线程库: 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以"pthread_"打头的 要使用这些函数库,要通过引入头文<pthread.h> 链接这些线程函数库时要使用编译器命令的"-lpthread"选项 pthread_create函数 功能:创建一个新的线程 原型 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_r