LoveStackover的博客

编程小子

多线程之Barrier和Rwlock的小理论知识(五)

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 don’t 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 Reader–Writer 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 Reader–Writer 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. Don’t 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:为了防止篇幅过长,实验部分单独记录。^ _ ^

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LoveStackover/article/details/79301719
个人分类: UNIX C编程
想对作者说点什么? 我来说一句

c#多线程之生产者消费者

2017年09月01日 18KB 下载

没有更多推荐了,返回首页

不良信息举报

多线程之Barrier和Rwlock的小理论知识(五)

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭