天天看点

AUPE学习第十二章------线程控制

本章讨论同一进程中的多个线程之间如何保持数据的私有性,最后讨论基于进程的系统调用如何与线程进行交互。

可以通过sysconfig函数来得到系统中的限制,包括线程限制。这些限制是为了增强应用程序在不同的操作系统实现之间的可移植性。

12.3线程属性

线程属性的数据类型是pthread_attr_t结构的指针。

可以用下面的方法初始化和去除线程的属性:

#include  <pthread.h>

int  pthread_attr_init(  pthread_attr_t  *attr)

int  pthread_attr_destroy( pthread_attr_t  *attr)

我们可以用专门的函数来得到和修改线程属性的各种值。

线程的属性主要有:线程的分离状态、线程栈末尾的警戒缓冲区大小、线程栈的最低地址、线程栈的大小。

可以用下面的函数得到线程的分离状态:

#include  <pthread.h>

int pthread_attr_getdetachstat( const  pthread_attr_t  *restrict  attr,  int  *detachstate);

int  pthread_attr_setdetachstate( pthread_attr_t  *attr,  int  detachstate)

分离状态创建线程:

[[email protected] apue]# cat page315.c 
#include "apue.h"
#include <pthread.h>

int makethread(void * (*fn)(void *), void *arg)
{
        int err;
        pthread_t tid;
        pthread_attr_t attr;
        err = pthread_attr_init(&attr);
        if(err != 0)
                return (err);
        err = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        if(err == 0)
                err = pthread_create(&tid, &attr, fn, arg);
        pthread_attr_destory(&attr);
        return(err);
}
           

通过_POSIX_THREAD_ATTR_STACKADDR和_POSIX_THREAD_ATTR_STACKSIZE这两个符号来检查系统是否支持线程栈属性。如果定义了,则支持。

注意区分线程属性和线程栈属性。可以通过下面两个函数来查询和修改线程栈属性:

int  pthread_attr_getstack(  const  pthread_attr_t  *restrict  attr,  void  **restrict  statckaddr,  size_t  *restrict  stacksize)

int  pthread_attr_setstack(  const  pthread_attr_t  *attr,  void  *stackaddr,  size_t  *stacksize)

这两个函数也可以用于确定栈的最高和最低地址。

可以用下面两个函数设置或者读取线程属性stacksize。

int  pthread_attr_getstacksize(cosnt  pthread_attr_t  *restrict  attr,  size_t   *restrict  stacksize)

int  pthread_attr_setstacksize(pthread_attr_t  *attr,  size_t  stacksize)

guardsize函数控制着线程栈末尾之后用以避免栈溢出的扩展内存的大小。下面函数用于操作:

int  pthread_attr_getguardsize(  const  pthread_attr_t  *restrict  attr,  size_t  *restrict  guardsize)

int  pthread_attr_setguardsize(  const  pthread_attr_t  *attr,  size_t  *guardsize)

线程还有一些没在pthread_attr_t结构中表达的属性:可取消状态、可取消类型、并发度。

并发度控制着用户级线程可以映射的内核线程或进程的数目。用下面函数得到和设置:

int   pthread_getconcurrency(void)

int   pthread_setconcurrency(int  level)

用户级线程和内核级线程的差别:

内核级线程是操作系统内核实现、管理和调度的一种线程。由于有操作系统管理,所以操作系统是知道线程的存在,并为其安排时间片

,管理与其有关的内核对象。因为内核级线程是由内核来管理,所以每次线程创建、切换都要执行一个模式切换例程,所以内核级线程

效率比较低,而且内核级线程的调度是由操作系统的设计者来决定的,所以缺乏灵活性。但是内核级线程有一个有点就是当一个进程的

某个线程因为一个系统调用或者缺页中断而阻塞时,不会导致该进程的所有线程阻塞。

内核级线程的优点:   较好的并行能力,一个进程内的线程阻塞不会影响该进程内的其他线程

内核级线程的缺点:  线程管理的开销过大,缺乏灵活性。

用户级线程是通过运行在用户态的运行时库来管理的,其优点是,线程的一切(包括调度、创建)都可以完全由用户自己决定,

所以具有较高的灵活性。而且由于是在用户态上进行管理,所以就省去了内核管理的开销,所以具有高效率。 但是用户级线程

有一个致命的缺点:一个进程内的某一个线程阻塞将导致整个进程内的所有线程全部阻塞。而且由于用户级线程没有时间片概

念,所以每个线程必须运行一段时间后将CPU让个其他的线程使用,否则,该线程将独占CPU。

用户级线程的优点: 有较高的灵活性和高效率

用户级线程的缺点: 较差并发能力

12.4同步属性

线程有属性,线程的同步对象也有属性。同步对象有互斥量、读写锁、条件变量。

可以用下面两个函数初始化和撤销互斥量的属性:

int   pthread_mutexattr_init( pthread_mutexattr_t  *attr)

int   pthread_mutexattr_destroy( pthread_mutexattr_t   *attr)  

互斥量同步对象的两个主要属性是:进程共享和类型。

在进程中,多个线程可以访问同一个同步对象。

多个进程也可以共享一个存储区域,称之为进程共享互斥量。可以用于进程的同步。下面的函数设置和修改进程共享互斥量的属性:

int   pthread_mutexattr_getpshared( const  pthread_mutexattr_t  *  restrict  attr,  int  *restrict  pshared)

int   pthread_mutexattr_setpshared( pthread_mutexattr_t   *attr,  int   pshared)

可以用下面函数得到和修改互斥量类型属性:

int   pthread_mutexattr_gettype( const  pthread_mutexattr_t  * restrict  attr,  int  *restrict  type)

int   pthread_mutexattr_settype(pthread_mutexattr_t   *attr,  int   type)

读写锁也有属性,读写锁属性用pthread_rwlockattr_t结构。可以用下面两个函数来初始化和回收读写锁属性。

int   pthread_rwlockattr_init(  pthread_rwlockattr_t   *attr)

int   pthread_rwlockattr_destroy( pthread_rwlockattr_t  *attr)

读写锁唯一支持的属性是进程共享属性。



继续阅读