11.线程

说明:本文是在阅读《unix环境高级编程》后做的一点摘要(自己认为重要的),如果有误或不清楚的地方请参考man手册和POSIX及其他官方文档,可以的话麻烦留言指出(十分感谢)。

1、线程标识

  • 线程比较
    int pthread_equal(pthread_t t1, pthread_t t2);
    RETURN VALUE: equal returns a nonzero value; otherwise returns 0.
    
  • 获取自身ID
    pthread_t pthread_self(void);
    
  • 线程创建
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                            void *(*start_routine) (void *), void *arg);
    
    • 新创建的线程可以访问进程地址空间,并继承调用线程的浮点环境和信号屏蔽字,但该线程的挂起信号会被删除
    • 调用失败返回错误码,不设置errno
    • thread参数不能安全的传给新线程
    • thread在solaris上返回的不是地址,FreeBSD返回指向线程数据结构的指针,Mac OS X的新线程地址不在一个范围,linux用无符号长整型表示(看起像指针)

2、线程终止

  • 1.从启动例程返回
  • 2.被同一进程中的其他线程取消
    int pthread_cancel(pthread_t thread);
    
    • 但是线程可以选择忽略被取消或者控制如何被取消,pthread_cancel仅仅提出请求
    • 一个线程可以建立多个清理程序
      void pthread_cleanup_push(void (*routine)(void *),
                                      void *arg);
      void pthread_cleanup_pop(int execute);
      
      • 按照注册时相反的顺序执行
      • routine在一下情况由pthread_cleanup_push调度
        • 调用pthread_exit
        • 响应取消
        • 非零execute参数调用pthread_cleanup_pop
      • 因为可以是宏实现,必须配对使用
      • 注意直接return是不会调用的
  • 3.线程调用pthread_exit
    void pthread_exit(void *retval);
    
    • 可通过下面的函数得到retval指针
      int pthread_join(pthread_t thread, void **retval);
      
      • 如果线程简单的返回,retval包含返回码
      • 如果线程被取消,retval指定的内容为PTHREAD_CANCELED
      • 如果线程处于游离状态,pthread_join调用会失败,返回EINVAL(与具体实现相关)
        int pthread_detach(pthread_t thread);
        

3、线程同步

  • 1.互斥量
    pthread_mutex_init(...)
    ...
    
  • 2.函数pthread_mutex_timelock
    pthread_mutex_timelock(pthread_mutex_t *restrict mutex,
        const struct timespec *restrict tsptr);
    
    • tsptr指绝对时间
      -3.读写锁(也叫共享互斥锁)
    • 与互斥量类似但是并行性更高(三种状态:读加锁,写加锁,不加锁)
    int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
     const pthread_rwlockattr_t *restrict attr);
     int pthread_rwlock_destory(pthread_rwlock_t *rwlock);
     int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
     int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
     int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
    
    • 错误返回值针对不正确使用读写锁的情况(未初始或死锁)

4.带超时的读写锁

int pthread_rwlock_timerdlock(pthread_rwlock_t *restrict rwlock,
    const struct timespec *restric tsptr);
int pthread_rwlock_timewrlock(pthread_rwlock_t *restrict rwlock,
    const struct timespec *restric tsptr);

5.条件变量

  • 给多个线程提供了一个会和的场所,允许线程无竞争方式等待特定条件发生
```c
int pthread_cond_init( pthread_cond_t *restrict cond,
        pthread_mutex_t *restrict mutex);
int pthread_cond_destory( pthread_cond_t *restrict cond);
int pthread_cond_wait(pthread_cond_t *restrict cond,
        pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
        pthread_mutex_t *restrict mutex,
        const struct timespec *restric tsptr);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
```
 - 这里的超时是时间是绝对时间

6.自旋锁

  • 不睡眠,忙等,在非抢占式内核中时非常有用
 int pthread_spin_init(..);
 int pthread_spin_destory(..);
 int pthread_spin_lock(..);
 int pthread_spin_trylock(..);
 int pthread_spin_unlock(..);

7.屏障

  • 允许每个线程等待,直到所有合作的线程都达到某一点,然后从该点继续执行
 int pthread_barrier_init(..);
 int pthread_barrier_destory(..);
 int pthread_barrier_wait(..);
  • 最后一个线程wait之后就满足了屏障计数,所有线程被唤醒
  • 举例如分解堆排序
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:上身试试 返回首页