1. 理论部分
1.1 Barriers
Barriers 比较重要的两个概念:
- A barrier allows each thread to wait until all cooperating threads have reached the same point, and then continue executing from there.
- but the threads dont have to exit. They can continue working after all threads have reached the barrier.
- #include <pthread.h>
- int pthread_barrier_init(pthread_barrier_t *restrict barrier, const pthread_barrierattr_t *restrict attr, unsigned int count);
- int pthread_barrier_destroy(pthread_barrier_t *barrier);
- Both return: 0 if OK, error number on failure
- int pthread_barrier_wait(pthread_barrier_t *barrier);
- Returns: 0 or PTHREAD_BARRIER_SERIAL_THREAD if OK, error number on failure
Barriers 的使用方式中, 值得关注几个小点:
- When we initialize a barrier, we use the count argument to specify the number of threads that must reach the barrier before all of the threads will be allowed to continue
- The thread calling pthread_barrier_wait is put to sleep if the barrier count (set in the call to pthread_barrier_init) is not yet satisfied. If the thread is the last one to call pthread_barrier_wait, thereby satisfying the barrier count, all of the threads are awakened.
- To one arbitrary thread, it will appear as if the pthread_barrier_wait function returned a value of PTHREAD_BARRIER_SERIAL_THREAD.This allows one thread to continue as the master to act on the results of the work done by all of the other threads.
在上一篇的记录里面, 我使用了 variable condition 来同步主子线程, 现在完全可以用 barrier 来达到同样的效果, 并且同步效果应好于前者, 相关的实验就不重复了
- 1.2 Barriers attribute
- #include <pthread.h>
- int pthread_barrierattr_init(pthread_barrierattr_t *attr);
- int pthread_barrierattr_destroy(pthread_barrierattr_t *attr);
- Both return: 0 if OK, error number on failure
- int pthread_barrierattr_getpshared(const pthread_barrierattr_t * restrict attr, int *restrict pshared);
- int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared);
- Both return: 0 if OK, error number on failure
- The only barrier attribute currently defined is the process-shared attribute, which controls whether a barrier can be used by threads from multiple processes or only from within the process that initialized the barrier.
- 1.3 ReaderWriter Locks
多个线程可以同时持有 read rwlock, 但是同时只有一个线程可以持有 write rwlock 听起来很适合多读, 少写的场合当一个线程持有 write rwlock, 其他线程无论读和写都得等其释放锁, 而当其持有 read rwlock 时, 别的线程也可以同时获取 read rwlock 此时如果别的线程希望获得 write rwlock, 那么也得等所有持有 read rwlock 的线程全部释放锁
但是存在一个问题: 可能想获取 write rwlock 的线程永远没有机会得到锁, 因为进行 read rwlock 的线程源源不断 为了想清楚这个问题, 笔者看了下 MAN pthread_rwlock_trywrlock:
- The calling thread may deadlock if at the time the pthread_rwlock_wrlock is made it holds the read-write lock (whether a read or write lock).// rwlock deadlock 的场合有点特别哦!
- Implementations may favor writers over readers to avoid writer starvation.
只是给出了一句模棱两可的话, 很是奇怪, 我的猜想: read rwlock 会有次数限制, 超过一定次数就会阻塞接下来的 read rwlock
- #include <pthread.h>
- #include <time.h>
- int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr);
- int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
- Both return: 0 if OK, error number on failure
- int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
- int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
- int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
- All return: 0 if OK, error number on failure
- int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict tsptr);
- int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rwlock, const struct timespec *restrict tsptr);
- Both return: 0 if OK, error number on failure
读比写频繁的场合, 使用 rwlock 更适合, 不由自主的想到上述的 write rwlock 被饿死的情况不过还是简单的记着这点, 并加以运用就行
- 1.4 ReaderWriter attribute
- #include <pthread.h>
- int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
- int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);
- Both return: 0 if OK, error number on failure
- int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t * restrict attr, int *restrict pshared);
- int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared);
- Both return: 0 if OK, error number on failure
rwlock 就一个属性: process-shared, 和 mutex 一样决定了是否能在多个进程之间共享此锁
2. 实验部分
题目一:
In the example code shown in Figure 11.14, what additional synchronization (if any) is necessary to allow the master thread to change the thread ID associated with a pending job? How would this affect the job_remove function?
题目二:
Apply the techniques shown in Figure 11.15 to the worker thread example (Figures 11.1 and 11.14) to implement the worker thread function. Dont forget to update the queue_init function to initialize the condition variable and change the job_insert and job_append functions to signal the worker threads. What difficulties arise?
题目三:
- What synchronization primitives would you need to implement a barrier ? Provide an implementation of the pthread_barrier_wait
- function.
NOTE: 为了防止篇幅过长, 实验部分单独记录 ^ _ ^
来源: http://blog.csdn.net/lovestackover/article/details/79301719