《Unix高级环境编程》 第十一章 Threads

来源:互联网 发布:税务申报软件 编辑:程序博客网 时间:2024/06/04 04:47

在本章,我们提出thread的概念并且讨论POSIX1中创建和摧毁线程的原始操作。我们也提出线程同步问题。我们讨论三种基础的同步机制-互斥量、读写锁、条件变量,并且讲述如何使用它们来保护共享资源。

二、线程概念

1. 使用线程的程序能无视处理器的数量

2. thread包含表示execution context的必要信息有哪些?

  1. threads ID
  2. a set of register values
  3. a scheduling priority and policy
  4. a signal mask
  5. errno variable
  6. thread-specific data

3 线程间共享了哪些数据

  1. text of executable program
  2. program’s global and heap memory
  3. stacks
  4. file descriptors

三、Threads Identification

4. thread ID和PID的区别?pid_t和pthread_t的实现类型是什么?

PID是系统中唯一的
thread ID是在context of process内部的。

pid_t 一般是non-negative integer
pthread_t 为了移植性一般使用structure而不是整型,Linux中使用unsigned long integer实现

5. thread ID间如何比较?

使用pthread_equal
详细内容见链接Linix中thread function集合:http://blog.csdn.net/feather_wch/article/details/50855258

6. 如何获取自身thread ID?使用pthread_self

四、线程创建

7. 线程如何创建

使用pthread_create:http://blog.csdn.net/feather_wch/article/details/50855258

8. 线程的注意点

  1. 可以使用process的地址空间,并且继承调用者的float-point enviornmentsignal mask
  2. 但是: the set of pending signals都被清除
  3. 若要在新建thread中得到thread ID,不要将create的参数thread的值传递给新线程,因为可能在pthread_create返回前,新线程就开始执行了,那么thread是垃圾值。
  4. Linux有过用clone实现thread的可能

五、Thread Termination

9-thread中调用_Exit,exit和_exit 会中止整个进程

10-仅仅中止thread而不是整个进程的三种方法

  1. thread简单地从start routine return
  2. thread可以被同个进程中其他的thread 取消
  3. thread可以调用pthread_exit,见链接:http://blog.csdn.net/feather_wch/article/details/50855258

11-pthread_join注意点

链接:http://blog.csdn.net/feather_wch/article/details/50855258
* 如果相关线程被取消,retval被设置为PTHREAD_CANCELED
* 通过调用pthread_join,我们自动将pthread设置为detached state,这样的他的资源可以被恢复。
* 如果调用pthread_join的线程已经处于detached state,出错并且返回EINVAL

12-线程中return和pthread_exit区别

return仅能返回整数
pthread_exit能返回更多得信息,比如返回结构体,如果该结构体是局部变量分配的,那么可能会被改变内容。可以使用全局变量或者malloc

13-pthread_cancel注意点

pthread_cancel链接:http://blog.csdn.net/feather_wch/article/details/50855258
pthread_cancel不等待thread terminate, 仅仅是发送请求

14-thread cleanup handlers

pthread_cleanup_push, pthread_cleanup_pop :http://blog.csdn.net/feather_wch/article/details/50855258
类似于atexit,用于注册线程的清理函数(清理函数用于执行相关资源清理的操作)。这些handlers(服务函数)保存在stack(栈)中,意味着它们以注册的反序执行

15- thread清理服务函数的注意点

  • 如果线程通过在其开始程序中return,其cleanup handlers就不会调用

15- process和thread相关的primitives

figure 11.6

16- 被detach(分离)的线程,pthread_join是不能用来wait线程的中止状态的

pthread_join used to wait detached thread will fail, return EINVAL

17- 如何分离线程?

使用pthread_detach

pthread_detach - detach a thread

#include <pthread.h>int pthread_detach(pthread_t thread);        //returns: 0 if OK, error number on error

18-How to create detached thread?

可以在使用pthread-create创建线程时通过attribute属性参数来得到分离的线程

六、Thread Synchronization

19-mutex是什么?如何同步?mutex变量的类型是什么?

  • mutex是pthread mutual-exclusion interfaces
  • mutex是通过在同一时间只有单一线程能访问和改变数据来实现同步
  • mutex variable type: pthread_mutex_t

20-pthread_mutex_init 和 pthread_mutex_destroy的作用?

具体原型可以查看LinuxAPI集合链接:http://blog.csdn.net/feather_wch/article/details/50855258
* init会将mutex初始化为常量PTHREAD_MUTEX_INITIALIZER
* attr = NULL时,mutex初始化为default attributes(默认属性)
* 如果是动态分配的mutex,在释放mutex之前需要调用destroy
* 需要对mutex的所有操作结束后,才能调用destroy

21-如何对mutex上锁和解锁?

使用pthread_mutex_lock, pthread_mutex_trylock, pthread_mutex_unlock,见链接:http://blog.csdn.net/feather_wch/article/details/50855258

  • trylock的特性是:如果mutex没有上锁,则上锁,然后返回0; 如果mutex已经上锁,trylock会失败,返回EBUSY,不会阻塞

22-如何避免死锁?

  • 所有的线程总是在mutex B上锁前给mutex A上锁,就绝对不会发生死锁
  • 可以使用trylock,在发现已经上锁后,先释放mutex然后再trylock,能防止死锁

23-如果很粗糙地处理lock的间隔(granularity),可能会导致同一个锁上阻塞过多的线程,这样在并发上提升的性能很有限

24-Reader-Writer Locks(读写锁)是什么?和mutex的区别是什么?

读写锁类似于互斥量。
mutex:只有两种状态,locked,unlocked
读写锁:三种状态,write-locked,read-locked,unlocked

25-读写锁有哪些API?作用是什么?

pthread_rwlock_init
pthread_rwlock_destroy
pthread_rwlock_rdlock
pthread_rwlock_wrlock
pthread_rwlock_unlock
pthread_rwlock_tryrdlock
pthread_rwlock_trywrlock

具体见链接的详细讲解:http://blog.csdn.net/feather_wch/article/details/50855258

26-读写锁注意点

  • 动态分配的rwlock需要在释放前调用 destroy,不然该lock所占有的资源会丢失
  • 实现在shared mode(read-locked)下有数量限制,因此我们需要检查rdlock的返回值
  • rwlock、unlock仅在使用未初始化的锁 或者 试图获得本身已经拥有的锁 这两种情况下返回错误值,一般我们不需要检查返回值。

27- pthread_rwlock_tryrdlock/trywrlock作用

类似于mutex的trylock,适合用于lock hierarchy不足以避免死锁的情况

Condition Variables

条件变量 provide a place for threads to rendezvous(约会,集合点).

28- 条件变量初始化的两种方法

  1. 静态初始化,PTHREAD_COND_INITIALIZER
  2. 动态初始化,pthread_cond_init

init中,当attr = NULL时,使用默认属性。

29 -pthread_cond_wait/timedwait作用和使用方法

wait是等待condition(条件)为真,wait return时,mutex自动上锁

timewait等待一定时间,超时则会报错,返回ETIMEDOUT

timewait中timespec的结构体的使用方法

struct timespec{    time_t tv_sec;  /*seconds*/    long tv_nsec;   /*nanoseconds*/};

将现在的时间+3分钟,来表示等待3分钟

30-获得绝对时间的方法(将timeval转换成timespec)

我们使用gettimeofday获取当前时间,并且用结构体timeval表示,之后需要将其转换为timespec结构体。
代码如下:

#include <sys/time.h>#include <stdlib.h>void maketimeout(struct timespec *tsp, long minutes){    struct timeval now;    /* get the current time */    gettimeofday(&now, NULL);    tsp->tv_sec = now.tv_sec;    tsp->tv_nsec = now.tv_usec * 1000; /* usec to nsec */    /* add the offset to get timeout value */    tsp->tv_sec += minutes * 60;}

31-pthread_cond_signal/broadcast作用

当condition满足的时候,pthread_cond_signal将会唤醒一个等待在condition的线程。

  • condition是work queue的状态
  • 我们网work queue放入信息的时候,必须拥有mutex
  • 想等待中的thread发送signal的时候,我们不需要用有mutex
  • thread苏醒的时候发现queue仍然是empty的,就会回到等待状态。不允许这种race(竞争)的话,我们需要在signal(发信号)给threads的时候,需要hold the mutex.
0 0
原创粉丝点击