之前的文章讨论了互斥量、条件变量、读写锁和自旋锁用于线程的同步,本文将首先讨论Barriers和信号量的使用,并给出了相应的代码和注意事项,相关代码也可在我的github上下载,然后对线程各种同步方法进行了比较。
Barriers
Barriers是一种不同于前面线程同步机制,它主要用于协调多个线程并行(parallel)共同完成某项任务。一个barrier对象可以使得每个线程阻塞,直到所有协同(合作完成某项任务)的线程执行到某个指定的点,才让这些线程继续执行。前面使用的pthread_join调用也可以看成简单的barrier,那里主线程要求其他线程都退出后,才能继续执行。可以使用接口pthread_barrier_init来初始化一个对象,用phread_barrier_destory来销毁一个barrier对象。他们声明如下:
#include <pthread.h>
int pthread_barrier_destroy(pthread_barrier_t *barrier);
int pthread_barrier_init(pthread_barrier_t *restrict barrier,
const pthread_barrierattr_t *restrict attr, unsigned count);
当使用pthread_barrier_init接口初始化hygienebarrier对象时,参数count指定需要多少个线程执行到指定的点,才能使得所有线程继续往下执行。每个线程执行的指定的点是指线程自身通过调用pthread_barrier_wait来表明当前线程执行到指定点了,等待其他线程调用pthread_barrier_wait。pthread_barrier_wait声明如下:
#include <pthread.h>
int pthread_barrier_wait(pthread_barrier_t *barrier);
该函数返回0,表明还需要等待其他线程调用pthread_barrier_wait,返回PTHREAD_BARRIER_SERIAL_THREAD表明所有线程可以继续往下执行了,具体那个线程返回PTHREAD_BARRIER_SERIAL_THREAD则是随机的。下面是用barrier来实现多个线程的排序,代码如下:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <limits.h>
#include <sys/time.h>
#define NTHR 8 /* number of threads */
#define NUMNUM 800L /* number of numbers to sort */
#define TNUM (NUMNUM/NTHR) /* number to sort per thread */
long nums[NUMNUM];
long snums[NUMNUM];
pthread_barrier_t b;
#define heapsort qsort
/*
* Compare two long integers (helper function for heapsort)
*/
int complong(const void *arg1, const void *arg2)
{
long l1 = *(long *)arg1;
long l2 = *(long *)arg2;
if (l1 == l2)
return 0;
else if (l1 < l2)
return -1;
else
return 1;
}
/*
* Worker thread to sort a portion of the set of numbers.
*/
void * thr_fn(void *arg)
{
long idx = (long)arg;
heapsort(&nums[idx], TNUM, sizeof(long), complong);
pthread_barrier_wait(&b);
/*
* Go off and perform more work ...