pthread_join
使一个线程等待另一个线程结束。代码中如果没有pthread_join
主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join
后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *thread_function(void *arg);
char message[] = "Hello World";
int main()
{
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_create(&a_thread, NULL, thread_function, (void *)message);
if (res != 0)
{
perror("Thread creation failed!");
exit(EXIT_FAILURE);
}
printf("Waiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0)
{
perror("Thread join failed!\n");
exit(EXIT_FAILURE);
}
printf("Thread joined, it returned %s\n", (char *)thread_result);
printf("Message is now %s\n", message);
exit(EXIT_FAILURE);
}
void *thread_function(void *arg)
{
printf("thread_function is running. Argument was %s\n", (char *)arg);
sleep(3);
strcpy(message, "Bye!");
pthread_exit("Thank you for your CPU time!");
}
线程同步
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
int flag = 1;
void *thread_function(void *arg);
int main()
{
int res;
pthread_t a_thread;
void *thread_result;
int count = 1;
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0)
{
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
while (count++ <= 20)
{
if (flag == 1)
{
printf ("1");
flag = 2;
}
else
{
sleep(1);
}
}
printf("\nWaiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0)
{
perror("Thread join failed");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
int count = 1;
while (count++ <= 20)
{
if (flag == 2)
{
printf("2");
flag = 1;
}
else
{
sleep(1);
}
}
}
设置线程为detachstate属性。表示新线程是否与进程中其他线程脱离同步,如果设置为PTHREAD_CREATE_DETACHED
则新线程不能用pthread_join()
来同步,且在退出时自行释放所占用的资源。缺省为PTHREAD_CREATE_JOINABLE
状态。这个属性也可以在线程创建并运行以后用pthread_detach()
来设置,而一旦设置为PTHREAD_CREATE_DETACH
状态(不论是创建时设置还是运行时设置)则不能再恢复到PTHREAD_CREATE_JOINABLE
状态
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
void *thread_function(void *arg);
char message[] = "Hello World";
int thread_finished = 0;
int main()
{
int res;
pthread_t a_thread;
pthread_attr_t thread_attr;
res = pthread_attr_init(&thread_attr);
if (res != 0)
{
perror("Attribute creation failed");
exit(EXIT_FAILURE);
}
res = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
if (res != 0)
{
perror("Setting detached attribute failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, &thread_attr, thread_function, (void*)message);
if (res != 0)
{
perror("Thread creation failed");
exit(EXIT_FAILURE);
}
pthread_attr_destroy(&thread_attr);
while(!thread_finished)
{
printf("Waiting for thread to say it's finished...\n");
sleep(1);
}
printf("Other thread finished, bye!\n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
printf("thread_function is running. Argument was %s\n", (char *)arg);
sleep(4);
printf("Second thread setting finished flag, and exiting now\n");
thread_finished = 1;
pthread_exit(NULL);
}
线程的被动结束分为两种,一种是异步终结,另外一种是同步终结。异步终结就是当其他线程调用 pthread_cancel
的时候,线程就立刻被结束。而同步终结则不会立刻终结,它会继续运行,直到到达下一个结束点(cancellation point)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void *thread_function(void *arg);
int main()
{
int res;
pthread_t a_thread;
void *thread_result;
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0)
{
perror("Thread create failed!");
exit(EXIT_FAILURE);
}
sleep(4);
printf("Canceling thread...\n");
res = pthread_cancel(a_thread);
if (res != 0)
{
perror("Thread cancel failed!");
exit(EXIT_FAILURE);
}
printf ("Waiting for thread to finished...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0)
{
perror ("Thread join failed!");
exit(EXIT_FAILURE);
}
printf("Thread canceled!");
exit(EXIT_FAILURE);
}
void *thread_function(void *arg)
{
int i;
int res;
res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
if (res != 0)
{
perror("Thread setcancelstate failed!");
exit(EXIT_FAILURE);
}
res = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
if (res != 0)
{
perror("Thread setcanceltype failed!");
exit(EXIT_FAILURE);
}
printf("thread_function is running...\n");
for (i = 0; i < 10; i++)
{
printf("Thread is still running (%d)...\n", i);
sleep(1);
}
pthread_exit(0);
}
多线程编程
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM 6
void *thread_function(void *arg);
int main()
{
int res;
pthread_t a_thread[NUM];
void *thread_result;
int index;
for (index = 0; index < NUM; ++index) {
res = pthread_create(&a_thread[index], NULL, thread_function, (void *)index);
if (res != 0)
{
perror("Thread create failed!");
exit(EXIT_FAILURE);
}
sleep(1);
}
printf("Waiting for threads to finished...\n");
for (index = NUM - 1; index >= 0; --index)
{
res = pthread_join(a_thread[index], &thread_result);
if (res == 0)
{
printf("Picked up a thread:%d\n", index + 1);
}
else
{
perror("pthread_join failed\n");
}
}
printf("All done\n");
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
int my_number = (int)arg;
int rand_num;
printf("thread_function is running. Argument was %d\n", my_number);
rand_num = 1 + (int)(9.0 * rand()/(RAND_MAX + 1.0));
sleep(rand_num);
printf("Bye from %d\n", my_number);
pthread_exit(NULL);
}
使用信号量进行线程同步
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>
#define SIZE 1024
void *thread_function(void *arg);
char buffer[SIZE];
sem_t sem;
int main()
{
int res;
pthread_t a_thread;
void *thread_result;
res = sem_init(&sem, 0, 0);
if (res != 0)
{
perror("Sem init failed");
exit(EXIT_FAILURE);
}
res = pthread_create(&a_thread, NULL, thread_function, NULL);
if (res != 0)
{
perror("Thread create failed");
exit(EXIT_FAILURE);
}
printf("Input some text. Enter 'end' to finish\n");
while (scanf("%s", buffer))
{
sem_post(&sem);
if (strncmp("end", buffer, 3) == 0)
break;
}
printf ("\nWaiting for thread to finish...\n");
res = pthread_join(a_thread, &thread_result);
if (res != 0)
{
perror("Thread join failed");
exit(EXIT_FAILURE);
}
printf ("Thread join\n");
sem_destroy(&sem);
exit(EXIT_SUCCESS);
}
void *thread_function(void *arg)
{
sem_wait(&sem);
while (strncmp("end", buffer, 3) != 0)
{
printf("You input %d characters\n", strlen(buffer));
sem_wait(&sem);
}
pthread_exit(NULL);
}
线程优先级调度
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <assert.h>
static int api_get_thread_policy (pthread_attr_t *attr)
{
int policy;
int rs = pthread_attr_getschedpolicy (attr, &policy);
assert (rs == 0);
switch (policy)
{
case SCHED_FIFO:
printf ("policy = SCHED_FIFO\n");
break;
case SCHED_RR:
printf ("policy = SCHED_RR");
break;
case SCHED_OTHER:
printf ("policy = SCHED_OTHER\n");
break;
default:
printf ("policy = UNKNOWN\n");
break;
}
return policy;
}
static void api_show_thread_priority (pthread_attr_t *attr,int policy)
{
int priority = sched_get_priority_max (policy);
assert (priority != -1);
printf ("max_priority = %d\n", priority);
priority = sched_get_priority_min (policy);
assert (priority != -1);
printf ("min_priority = %d\n", priority);
}
static int api_get_thread_priority (pthread_attr_t *attr)
{
struct sched_param param;
int rs = pthread_attr_getschedparam (attr, ¶m);
assert (rs == 0);
printf ("priority = %d\n", param.__sched_priority);
return param.__sched_priority;
}
static void api_set_thread_policy (pthread_attr_t *attr,int policy)
{
int rs = pthread_attr_setschedpolicy (attr, policy);
assert (rs == 0);
api_get_thread_policy (attr);
}
int main(void)
{
pthread_attr_t attr; // 线程属性
struct sched_param sched; // 调度策略
int rs;
/*
* 对线程属性初始化
* 初始化完成以后,pthread_attr_t 结构所包含的结构体
* 就是操作系统实现支持的所有线程属性的默认值
*/
rs = pthread_attr_init (&attr);
assert (rs == 0); // 如果 rs 不等于 0,程序 abort() 退出
/* 获得当前调度策略 */
int policy = api_get_thread_policy (&attr);
/* 显示当前调度策略的线程优先级范围 */
printf ("Show current configuration of priority\n");
api_show_thread_priority(&attr, policy);
/* 获取 SCHED_FIFO 策略下的线程优先级范围 */
printf ("show SCHED_FIFO of priority\n");
api_show_thread_priority(&attr, SCHED_FIFO);
/* 获取 SCHED_RR 策略下的线程优先级范围 */
printf ("show SCHED_RR of priority\n");
api_show_thread_priority(&attr, SCHED_RR);
/* 显示当前线程的优先级 */
printf ("show priority of current thread\n");
int priority = api_get_thread_priority (&attr);
/* 手动设置调度策略 */
printf ("Set thread policy\n");
printf ("set SCHED_FIFO policy\n");
api_set_thread_policy(&attr, SCHED_FIFO);
printf ("set SCHED_RR policy\n");
api_set_thread_policy(&attr, SCHED_RR);
/* 还原之前的策略 */
printf ("Restore current policy\n");
api_set_thread_policy (&attr, policy);
/*
* 反初始化 pthread_attr_t 结构
* 如果 pthread_attr_init 的实现对属性对象的内存空间是动态分配的,
* phread_attr_destory 就会释放该内存空间
*/
rs = pthread_attr_destroy (&attr);
assert (rs == 0);
return 0;
}
线程互斥锁
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
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)
{
/* Define and use local variables for convenience */
int i, start, end, offset, len ;
double mysum, *x, *y;
offset = (int)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[])
{
int 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);
}
线程中使用条件变量
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#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 *idp)
{
int j,i;
double result=0.0;
int *my_id = idp;
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 %d, count = %d Threshold reached.\n", *my_id, count);
}
printf("inc_count(): thread %d, count = %d, unlocking mutex\n", *my_id, count);
pthread_mutex_unlock(&count_mutex);
for (j=0; j<1000; j++)
result = result + (double)random();
}
pthread_exit(NULL);
}
void *watch_count(void *idp)
{
int *my_id = idp;
printf("Starting watch_count(): thread %d\n", *my_id);
pthread_mutex_lock(&count_mutex);
if (count<COUNT_LIMIT) {
pthread_cond_wait(&count_threshold_cv, &count_mutex);
printf("watch_count(): thread %d Condition signal received.\n", *my_id);
}
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
int i, rc;
pthread_t threads[3];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[0], &attr, inc_count, (void *)&thread_ids[0]);
pthread_create(&threads[1], &attr, inc_count, (void *)&thread_ids[1]);
pthread_create(&threads[2], &attr, watch_count, (void *)&thread_ids[2]);
for (i=0; i<NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
printf ("Main(): Waited on %d threads. Done.\n", NUM_THREADS);
pthread_attr_destroy(&attr);
pthread_mutex_destroy(&count_mutex);
pthread_cond_destroy(&count_threshold_cv);
pthread_exit(NULL);
}
设置线程栈
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NTHREADS 4
#define N 1000
#define MEGEXTRA 1000000
pthread_attr_t attr;
void *dowork(void *threadid)
{
double A[N][N];
int i,j,tid;
size_t mystacksize;
tid = (int)threadid;
pthread_attr_getstacksize (&attr, &mystacksize);
printf("Thread %d: 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, 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 %d threads.\n", t);
pthread_exit(NULL);
}