对 pthread api 进行归类, 可以分为四类:
线程管理
直接工作于线程, 如创建, 分离, 加入 (join) 等, 也包括设置或查询线程属性
(joinable, scheduling 等).
互斥量
处理同步的 mutex (mutual exclusion 的缩写), 如创建互斥量, 销毁互斥量,
锁定及解锁互斥量等, 也包括互斥量属性的设置与修改.
条件变量
处理线程之间的通信, 这些共享同一个 mutex, 如创建, 销毁, 等待, 通知
(singal), 也包括设置或查询条件变量的属性.
同步
管理读写锁和栅栏 (barrier).
pthread 库中所有的标识都以 pthread_ 开头, 如下表所示:
前缀 | 分组 |
---|---|
pthread_ | 与线程本身相关的指令组 |
pthread_attr_ | 线程属性对象 |
pthread_mutex_ | 互斥量s |
pthread_mutexattr_ | 互斥量属性对象 |
pthread_cond_ | 条件变量 |
pthread_condattr_ | 条件变量属性对象 |
pthread_key_ | 特定于线程的数据 keys (局部存储) |
pthread_rwlock_ | 读写锁 |
pthread_barrier_ | 同步栅栏 |
主要有下列的 api:
// 若 arg 为 NULL, 表示不向 start_routine() 传递参数
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void*),
void *restrict arg);
// value_ptr 为线程退出码, 由 pthread_join() 函数的第二个参数接收.
// 在 main() 中创建了线程, 然后显式调用本函数, main() 会等其它线程
//+都结束后才会结束.
void pthread_exit(void *value_ptr);
int pthread_cancel(pthread_t thread);
int pthread_attr_destroy(pthread_attr_t *attr);
int pthread_attr_init(pthread_attr_t *attr);
例 1: Pthread Creation and Termination
#include
#include
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
例2: Thread Argument Passing
#include
#include
#include
#define NUM_THREADS 8
char *messages[NUM_THREADS];
void *PrintHello(void *threadid)
{
int *id_ptr, taskid;
sleep(1);
id_ptr = (int *) threadid;
taskid = *id_ptr;
printf("Thread %d: %s\n", taskid, messages[taskid]);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int *taskids[NUM_THREADS];
int rc, t;
messages[0] = "English: Hello World!";
messages[1] = "French: Bonjour, le monde!";
messages[2] = "Spanish: Hola al mundo";
messages[3] = "Klingon: Nuq neH!";
messages[4] = "German: Guten Tag, Welt!";
messages[5] = "Russian: Zdravstvytye, mir!";
messages[6] = "Japan: Sekai e konnichiwa!";
messages[7] = "Latin: Orbis, te saluto!";
for(t=0;t<NUM_THREADS;t++) {
taskids[t] = (int *) malloc(sizeof(int));
*taskids[t] = t;
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskids[t]);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
例3: Thread Argument Passing
#include
#include
#include
#define NUM_THREADS 8
char *messages[NUM_THREADS];
struct thread_data
{
int thread_id;
int sum;
char *message;
};
struct thread_data thread_data_array[NUM_THREADS];
void *PrintHello(void *threadarg)
{
int taskid, sum;
char *hello_msg;
struct thread_data *my_data;
sleep(1);
my_data = (struct thread_data *) threadarg;
taskid = my_data->thread_id;
sum = my_data->sum;
hello_msg = my_data->message;
printf("Thread %d: %s Sum=%d\n", taskid, hello_msg, sum);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int *taskids[NUM_THREADS];
int rc, t, sum;
sum=0;
messages[0] = "English: Hello World!";
messages[1] = "French: Bonjour, le monde!";
messages[2] = "Spanish: Hola al mundo";
messages[3] = "Klingon: Nuq neH!";
messages[4] = "German: Guten Tag, Welt!";
messages[5] = "Russian: Zdravstvytye, mir!";
messages[6] = "Japan: Sekai e konnichiwa!";
messages[7] = "Latin: Orbis, te saluto!";
for(t=0;t<NUM_THREADS;t++) {
sum = sum + t;
thread_data_array[t].thread_id = t;
thread_data_array[t].sum = sum;
thread_data_array[t].message = messages[t];
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello,
(void *) &thread_data_array[t]);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
主要有下面 api:
// value_ptr 由 pthread_exit() 指定.
int pthread_join(pthread_t thread, void **value_ptr);
int pthread_detach(pthread_t thread);
int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
例 4: Pthread Joining
#include
#include
#include
#include
#define NUM_THREADS 4
void *BusyWork(void *t)
{
int i;
long tid;
double result=0.0;
tid = (long)t;
printf("Thread %ld starting...\n",tid);
for (i=0; i<1000000; i++)
{
result = result + sin(i) * tan(i);
}
printf("Thread %ld done. Result = %e\n",tid, result);
pthread_exit((void*) t);
}
int main (int argc, char *argv[])
{
pthread_t thread[NUM_THREADS];
pthread_attr_t attr;
int rc;
long t;
void *status;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(t=0; t<NUM_THREADS; t++) {
printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create()
is %d\n", rc);
exit(-1);
}
}
pthread_attr_destroy(&attr);
for(t=0; t<NUM_THREADS; t++) {
rc = pthread_join(thread[t], &status);
if (rc) {
printf("ERROR; return code from pthread_join()
is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld having a status
of %ld\n",t,(long)status);
}
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
不同的操作系统可以为线栈提供的栈大小不一样, 可以人为指定线程使用的栈大小
(要考虑操作系统的限制). 主要有下面的 api:
int pthread_attr_getstacksize(const pthread_attr_t *restrict attr,
size_t *restrict stacksize);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
int pthread_attr_getstackaddr(const pthread_attr_t *restrict attr,
void **restrict stackaddr);
int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr);
例 5: Stack Management
#include
#include
#define NTHREADS 4
#define N 1000
#define MEGEXTRA 1000000
pthread_attr_t attr;
void *dowork(void *threadid)
{
double A[N][N];
int i,j;
long tid;
size_t mystacksize;
tid = (long)threadid;
pthread_attr_getstacksize (&attr, &mystacksize);
printf("Thread %ld: stack size = %li bytes \n", tid, mystacksize);
for (i=0; i<N; i++)
for (j=0; j<N; j++)
A[i][j] = ((i*j)/3.452) + (N-i);
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t threads[NTHREADS];
size_t stacksize;
int rc;
long t;
pthread_attr_init(&attr);
pthread_attr_getstacksize (&attr, &stacksize);
printf("Default stack size = %li\n", stacksize);
stacksize = sizeof(double)*N*N+MEGEXTRA;
printf("Amount of stack needed per thread = %li\n",stacksize);
pthread_attr_setstacksize (&attr, stacksize);
printf("Creating threads with stack size = %li bytes\n",stacksize);
for(t=0; t<NTHREADS; t++){
rc = pthread_create(&threads[t], &attr, dowork, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
printf("Created %ld threads.\n", t);
pthread_exit(NULL);
}
pthread_t pthread_self(void);
int pthread_equal(pthread_t t1, pthread_t t2);
// 这是静态声明
pthread_once_t once_control = PTHREAD_ONCE_INIT;
int pthread_once(pthread_once_t *once_control,
void (*init_routine)(void));
主要有下面 api:
// 这是静态声明
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
主要有下面 api:
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
例 6: Using Mutexes
#include
#include
#include
typedef struct
{
double *a;
double *b;
double sum;
int veclen;
} DOTDATA;
#define NUMTHRDS 4
#define VECLEN 100
DOTDATA dotstr;
pthread_t callThd[NUMTHRDS];
pthread_mutex_t mutexsum;
void *dotprod(void *arg)
{
int i, start, end, len ;
long offset;
double mysum, *x, *y;
offset = (long)arg;
len = dotstr.veclen;
start = offset*len;
end = start + len;
x = dotstr.a;
y = dotstr.b;
mysum = 0;
for (i=start; i<end ; i++) {
mysum += (x[i] * y[i]);
}
pthread_mutex_lock (&mutexsum);
dotstr.sum += mysum;
pthread_mutex_unlock (&mutexsum);
pthread_exit((void*) 0);
}
int main (int argc, char *argv[])
{
long i;
double *a, *b;
void *status;
pthread_attr_t attr;
a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
for (i=0; i<VECLEN*NUMTHRDS; i++) {
a[i]=1.0;
b[i]=a[i];
}
dotstr.veclen = VECLEN;
dotstr.a = a;
dotstr.b = b;
dotstr.sum=0;
pthread_mutex_init(&mutexsum, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(i=0; i<NUMTHRDS; i++) {
pthread_create(&callThd[i], &attr, dotprod, (void *)i);
}
pthread_attr_destroy(&attr);
for(i=0; i<NUMTHRDS; i++) {
pthread_join(callThd[i], &status);
}
printf ("Sum = %f \n", dotstr.sum);
free (a);
free (b);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}
主要有下面 api:
// 这是静态声明
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
int pthread_condattr_destroy(pthread_condattr_t *attr);
int pthread_condattr_init(pthread_condattr_t *attr);
主要有下面 api:
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
例 7: Using Condition Variables
#include
#include
#include
#define NUM_THREADS 3
#define TCOUNT 10
#define COUNT_LIMIT 12
int count = 0;
int thread_ids[3] = {0,1,2};
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;
void *inc_count(void *t)
{
int i;
long my_id = (long)t;
for (i=0; i<TCOUNT; i++) {
pthread_mutex_lock(&count_mutex);
count++;
if (count == COUNT_LIMIT) {
pthread_cond_signal(&count_threshold_cv);
printf("inc_count(): thread %ld, count = %d Threshold reached.\n",
my_id, count);
}
printf("inc_count(): thread %ld, count = %d, unlocking mutex\n",
my_id, count);
pthread_mutex_unlock(&count_mutex);
sleep(1);
}
pthread_exit(NULL);
}
void *watch_count(void *t)
{
long my_id = (long)t;
printf("Starting watch_count(): thread %ld\n", my_id);
pthread_mutex_lock(&count_mutex);
while (count<COUNT_LIMIT) {
pthread_cond_wait(&count_threshold_cv, &count_mutex);
printf("watch_count(): thread %ld Condition signal received.\n", my_id);
count += 125;
printf("watch_count(): thread %ld count now = %d.\n", my_id, count);
}
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
int i, rc;
long t1=1, t2=2, t3=3;
pthread_t threads[3];
pthread_attr_t attr;
pthread_mutex_init(&count_mutex, NULL);
pthread_cond_init (&count_threshold_cv, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[0], &attr, watch_count, (void *)t1);
pthread_create(&threads[1], &attr, inc_count, (void *)t2);
pthread_create(&threads[2], &attr, inc_count, (void *)t3);
for (i=0; i<NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
printf ("Main(): Waited on %d threads. Done.\n", NUM_THREADS);
/* Clean up and exit */
pthread_attr_destroy(&attr);
pthread_mutex_destroy(&count_mutex);
pthread_cond_destroy(&count_threshold_cv);
pthread_exit(NULL);
}
int pthread_atfork (void (*prepare)(void),
void (*parent)(void),
void (*child)(void));
int pthread_attr_destroy (pthread_attr_t *attr);
int pthread_attr_getdetachstate (const pthread_attr_t *attr,
int *detachstate);
int pthread_attr_getguardsize (const pthread_attr_t *restrict attr,
size_t *restrict guardsize);
int pthread_attr_getinheritsched (const pthread_attr_t *restrict attr,
int *restrict inheritsched);
int pthread_attr_getschedparam (const pthread_attr_t *restrict attr,
struct sched_param *restrict param);
int pthread_attr_getschedpolicy (const pthread_attr_t *restrict attr,
int *restrict policy);
int pthread_attr_getscope (const pthread_attr_t *restrict attr,
int *restrict contentionscope);
int pthread_attr_getstack (const pthread_attr_t *restrict attr,
void **restrict stackaddr,
size_t *restrict stacksize);
int pthread_attr_getstackaddr (const pthread_attr_t *restrict attr,
void **restrict stackaddr);
int pthread_attr_getstacksize (const pthread_attr_t *restrict attr,
size_t *restrict stacksize);
int pthread_attr_init (pthread_attr_t *attr);
int pthread_attr_setdetachstate (pthread_attr_t *attr,
int detachstate);
int pthread_attr_setguardsize (pthread_attr_t *attr,
size_t guardsize);
int pthread_attr_setinheritsched (pthread_attr_t *attr,
int inheritsched);
int pthread_attr_setschedparam (pthread_attr_t *restrict attr,
const struct sched_param *restrict param);
int pthread_attr_setschedpolicy (pthread_attr_t *attr,
int policy);
int pthread_attr_setscope (pthread_attr_t *attr,
int contentionscope);
int pthread_attr_setstack (pthread_attr_t *attr,
void *stackaddr,
size_t stacksize);
int pthread_attr_setstackaddr (pthread_attr_t *attr,
void *stackaddr);
int pthread_attr_setstacksize (pthread_attr_t *attr,
size_t stacksize);
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);
int pthread_barrier_wait (pthread_barrier_t *barrier);
int pthread_barrierattr_destroy (pthread_barrierattr_t *attr);
int pthread_barrierattr_getpshared (const pthread_barrierattr_t * restrict attr,
int *restrict pshared);
int pthread_barrierattr_init (pthread_barrierattr_t *attr);
int pthread_barrierattr_setpshared (pthread_barrierattr_t *attr,
int pshared);
int pthread_cancel (pthread_t thread);
int pthread_cond_broadcast (pthread_cond_t *cond);
int pthread_cond_destroy (pthread_cond_t *cond);
int pthread_cond_init (pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
int pthread_cond_signal (pthread_cond_t *cond);
int pthread_cond_timedwait (pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
int pthread_cond_wait (pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
int pthread_condattr_destroy (pthread_condattr_t *attr);
int pthread_condattr_getclock (const pthread_condattr_t *restrict attr,
clockid_t *restrict clock_id);
int pthread_condattr_getpshared (const pthread_condattr_t *restrict attr,
int *restrict pshared);
int pthread_condattr_init (pthread_condattr_t *attr);
int pthread_condattr_setclock (pthread_condattr_t *attr,
clockid_t clock_id);
int pthread_condattr_setpshared (pthread_condattr_t *attr,
int pshared);
int pthread_create (pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void*),
void *restrict arg);
int pthread_detach (pthread_t thread);
int pthread_equal (pthread_t t1,
pthread_t t2);
int pthread_getconcurrency (void);
int pthread_getcpuclockid (pthread_t thread_id,
clockid_t *clock_id);
int pthread_getschedparam (pthread_t thread,
int *restrict policy,
struct sched_param *restrict param);
int pthread_join (pthread_t thread,
void **value_ptr);
int pthread_key_create (pthread_key_t *key,
void (*destructor)(void*));
int pthread_key_delete (pthread_key_t key);
int pthread_kill (pthread_t thread,
int sig);
int pthread_mutex_destroy (pthread_mutex_t *mutex);
int pthread_mutex_getprioceiling (const pthread_mutex_t *restrict mutex,
int *restrict prioceiling);
int pthread_mutex_init (pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
int pthread_mutex_lock (pthread_mutex_t *mutex);
int pthread_mutex_setprioceiling (pthread_mutex_t *restrict mutex,
int prioceiling,
int *restrict old_ceiling);
int pthread_mutex_timedlock (pthread_mutex_t *restrict mutex,
const struct timespec *restrict abs_timeout);
int pthread_mutex_trylock (pthread_mutex_t *mutex);
int pthread_mutex_unlock (pthread_mutex_t *mutex);
int pthread_mutexattr_destroy (pthread_mutexattr_t *attr);
int pthread_mutexattr_getprioceiling (const pthread_mutexattr_t * restrict attr,
int *restrict prioceiling);
int pthread_mutexattr_getprotocol (const pthread_mutexattr_t * restrict attr,
int *restrict protocol);
int pthread_mutexattr_getpshared (const pthread_mutexattr_t * restrict attr,
int *restrict pshared);
int pthread_mutexattr_gettype (const pthread_mutexattr_t *restrict attr,
int *restrict type);
int pthread_mutexattr_init (pthread_mutexattr_t *attr);
int pthread_mutexattr_setprioceiling (pthread_mutexattr_t *attr,
int prioceiling);
int pthread_mutexattr_setprotocol (pthread_mutexattr_t *attr,
int protocol);
int pthread_mutexattr_setpshared (pthread_mutexattr_t *attr,
int pshared);
int pthread_mutexattr_settype (pthread_mutexattr_t *attr,
int type);
int pthread_once (pthread_once_t *once_control,
void (*init_routine)(void));
int pthread_rwlock_destroy (pthread_rwlock_t *rwlock);
int pthread_rwlock_init (pthread_rwlock_t *restrict rwlock,
const pthread_rwlockattr_t *restrict attr);
int pthread_rwlock_rdlock (pthread_rwlock_t *rwlock);
int pthread_rwlock_timedrdlock (pthread_rwlock_t *restrict rwlock,
const struct timespec *restrict abs_timeout);
int pthread_rwlock_timedwrlock (pthread_rwlock_t *restrict rwlock,
const struct timespec *restrict abs_timeout);
int pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock);
int pthread_rwlock_unlock (pthread_rwlock_t *rwlock);
int pthread_rwlock_wrlock (pthread_rwlock_t *rwlock);
int pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr);
int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t * restrict attr,
int *restrict pshared);
int pthread_rwlockattr_init (pthread_rwlockattr_t *attr);
int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr,
int pshared);
int pthread_setcancelstate (int state,
int *oldstate);
int pthread_setcanceltype (int type,
int *oldtype);
int pthread_setconcurrency (int new_level);
int pthread_setschedparam (pthread_t thread,
int policy,
const struct sched_param *param);
int pthread_setschedprio (pthread_t thread,
int prio);
int pthread_setspecific (pthread_key_t key,
const void *value);
int pthread_sigmask (int how,
const sigset_t *restrict set,
sigset_t *restrict oset);
int pthread_spin_destroy (pthread_spinlock_t *lock);
int pthread_spin_init (pthread_spinlock_t *lock,
int pshared);
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 sigprocmask (int how,
const sigset_t *restrict set,
sigset_t *restrict oset);
pthread_t pthread_self (void);
void *pthread_getspecific (pthread_key_t key);
void pthread_cleanup_pop (int execute);
void pthread_cleanup_push (void (*routine)(void*),
void *arg);
void pthread_exit (void *value_ptr);
void pthread_testcancel (void);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_once_t once_control = PTHREAD_ONCE_INIT;
``