APUE 学习笔记——线程

1、线程的优点

  • 通过为每种事件类型分配单独的处理线程,可以简化处理异步事件的代码
  • 多个进程必须使用操作系统提供的复杂机制才能实现内存共享和文件描述符的共享。而多线程能自动地访问相同的存储空间和文件描述符
  • 有些问题可以分解从而提高整个程序的吞吐量(多线程中,相互独立的任务的处理可以交叉进行)
  • 交互式程序可以通过多线程改善响应时间(多线程可以把程序中处理用户的输入输出部分与其他部分分开)

2、线程之间共享的属性有哪些?特有的属性有哪些?

  • 共享的包括:可执行程序的代码、程序的全局内存和堆内存、栈、以及文件描述符
  • 特有的:进程中标识线程的线程ID、一组寄存器值、栈、调度优先级和策略、信号屏蔽字、errno变量、以及线程私有数据

3、什么情况会造成死锁?如何避免死锁?

  • 如果线程试图对同一个互斥量加锁两次,则它自身就会陷入死锁状态
  • 如果程序中使用了两个互斥量 Mutex1,Mutex2;线程A锁住了 Mutex1并请求锁住 Mutex2;线程B锁住了 Mutex2并请求锁住 Mutex1,所以这两个线程都无法向前进行,导致死锁

一般可以通过仔细控制互斥量加锁的顺序来避免死锁的发生。假设要同时对互斥量 M1,M2,M3同时加锁。如果所有线程总是在对互斥量M2锁住之前先锁住互斥量M1,在对互斥量M3锁住之前先锁住互斥量M2,那么就不会发生死锁

还有一种办法是使用pthread_mutex_trylock接口并执行多次测试。一旦多次试图锁住互斥量都失败,则立即释放自己锁定的互斥量。

4、读写锁或者共享锁的加锁规则?

  • 当读写锁是写锁定状态时,在该锁被解锁之前,所有试图对这个锁加锁(无论是加读锁还是价写锁)的线程都会被阻塞
  • 当读写锁是读锁定状态时,所有试图对它加读锁的线程都可以获得访问权,但是所有试图对它加写锁的线程都会被阻塞

通常如果读写锁处于读锁定的状态,此时有一个线程试图对这个读写锁加写锁时,读写锁会阻塞该加写锁请求之后任何线程的所有加读锁请求。因为如果不阻塞之后的所有加读锁请求,那么当后续不断有加读锁请求到来时,该锁始终处于读锁定的状态,那么那个加写锁请求将永远得不到满足

5、什么是条件变量?

  • 条件变量是不同于锁的另一种同步机制。条件变量给多个线程提供了一个会合的场所。
  • 条件本身是由互斥量来进行保护的,线程在改变条件的状态之前必须首先锁住互斥量。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待指定的条件发生

6、什么是自旋锁?

  • 自旋锁与互斥量类似,但是它并不是通过睡眠使得线程阻塞,而是在获得锁之前一直处于忙等(自旋)阻塞状态。此时CPU不能做其他的事情。
  • 自旋锁常用于以下情况:锁被持有时间很短,而且线程不希望在重新调度上花费太多的成本

7、什么是屏障?

  • 屏障 barrier 是用户协作多个线程并行工作的同步机制。屏障允许每个线程等待,直到所有的合作线程都到达某一点,然后从改点继续执行。
  • 调用 pthread_barrier_wait 的线程在屏障计数未满足条件时(即:到达屏障的线程数量小于count),会进入休眠状态。如果线程调用 pthread_barrier_wait 后,刚好满足了屏障计数条件,则返回 PTHREAD_BARRIER_SERIAL_THREAD ,同时所有的等待线程都将被唤醒(同时这些线程上的 pthread_barrier_wait 函数返回 0)。
  • 一旦到达屏障计数值,而且线程处于非阻塞状态,那么屏障就可以重用(即屏障计数有从零开始)。此时屏障的计数目标数量仍然不变。如果你希望改变计数的目标数量(比如扩大到达线程的目标数量),则必须再一次调用 pthread_barrier_init 函数。

API

int pthread_equal(pthread_t tid1,pthread tid2);

pthread_t pthread_self(void);

int pthread_create(pthread_t *restrict tidp,
    const pthread_attr_t *restrict attr,
    void *(*start_rtn)(void*),
    void *restrict arg);

void pthread_exit(void *rval_ptr);

int pthread_join(pthread_t tid,void **rval_pptr);

int pthread_cancel(pthread_t tid);

void pthread_cleanup_push(void (*rtn)(void*),void *arg);
void pthread_cleanup_pop(int execute);

int pthread_detach(pthread_t tid);

int pthread_mutex_init(pthread_mutex_t *restrict mutex,
    const pthread_mutexattr_t *restrict attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_timedlock(pthread_mutex_t *restrict mutex,
    const struct timespec *restrict tsptr);

int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
    const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_destroy(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);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock,
    const struct timespect*restrict tsptr);
int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock,
    const struct timespect*restrict tsptr);

int pthread_cond_init(pthread_cond_t *restrict cond,
    const pthread_condattr_t *restrict attr);
int pthread_cond_destroy(pthread_cond_t *cond);

int pthread_cond_wait(pthread_cond_t *restrict cond,
    pthread_mutext_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
    pthread_mutext_t *restrict mutex,
    const struct timespect*restrict tsptr);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);

int pthread_spin_init(pthread_spinlock_t *restrict lock,
    int pshared);
int pthread_spin_destroy(pthread_spinlock_t *lock);

int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
int pthread_spin_unlock(pthread_spinlock_t *lock);

int pthread_barrier_init(pthread_barrier_t *restrict barrier,
    const pthread_barrierattr_t *restrict attr,
    int count);
int pthread_barrier_destroy(pthread_barrier_t *barrier);

int pthread_barrier_wait(pthread_barrier_t * barrier);
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!