[Mac-10.7.1 Lion Intel-based x64 gcc4.2.1]
Q: c标准中包含线程操作么?
A: 没有。
Q: 给个mac下线程操作的例子吧。
A: 创建线程的函数可以实用pthread_create, 原型如下:
int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(*start_routine)(void *), void *restrict arg);thread是保存成功创建线程结构信息; attr表示线程的相关属性,start_routine表示线程执行的函数, arg表示线程执行的使用的参数。
示例代码(保存为testForC.c):
#include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> #define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue)); #define PRINT_STR(str) printf(#str" is %s\n", (str)); void *thread_one_func(void *args) { int i = 1; while (i > 0) { printf("thread: loop %d\n", i++); } return NULL; } int main() { pthread_t thread; int ret; ret = pthread_create(&thread, NULL, thread_one_func, NULL); if(ret != 0) { perror("pthread_create error"); return -1; } return 0; }运行:
可以看到,程序运行后然后很快就结束了,且没有任何输出。这是因为主线程过快结束导致结束了刚刚创建的子线程。
Q:如何让主线程不理解结束呢?
A: 可以让主线程进入等待状态,加入while(1)循环让主线程一直等待。
#include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> #define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue)); #define PRINT_STR(str) printf(#str" is %s\n", (str)); #define FOR_EVER() { while(1) ; } void *thread_one_func(void *args) { int i = 1; while (i > 0) { printf("thread: loop %d\n", i++); } return NULL; } int main() { pthread_t thread; int ret; ret = pthread_create(&thread, NULL, thread_one_func, NULL); if(ret != 0) { perror("pthread_create error"); return -1; } FOR_EVER(); return 0; }运行结果:
上面是在子线程输出字符串的过程中截取的,子线程会一直运行下去,知道自己的循环退出。
Q: 子线程运行的这么快,让它慢点行不?
A: 在子线程的while循环中加个延迟1秒的函数,如下:
#include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> #define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue)); #define PRINT_STR(str) printf(#str" is %s\n", (str)); #define FOR_EVER() { while(1) ; } void *thread_one_func(void *args) { int i = 1; while (i > 0) { printf("thread: loop %d\n", i++); sleep(1); // sleep for 1 second } return NULL; } int main() { pthread_t thread; int ret; ret = pthread_create(&thread, NULL, thread_one_func, NULL); if(ret != 0) { perror("pthread_create error"); return -1; } FOR_EVER(); return 0; }
从实际运行可以看出,子线程每打印一行会延迟一下。
Q: 主线程如何在规定的时间内干掉子线程?
A: 主线程可以启动定时器,在指定时间内干掉子线程。
int setitimer(int which, const struct itimerval *restrict value, struct itimerval *restrict ovalue);参数which表示定时器类型,value表示定时器时间信息,ovalue可以设置为NULL.
#include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sys/time.h> #include <sys/signal.h> #define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue)); #define PRINT_STR(str) printf(#str" is %s\n", (str)); #define FOR_EVER() { while(1) ; } pthread_t thread; int should_loop = 1; void kill_son_thread(int arg) { printf("now it will kill son thread...\n"); pthread_cancel(thread); should_loop = 0; } void *thread_one_func(void *args) { int i = 1; while (i > 0) { printf("thread: loop %d\n", i++); sleep(1); // sleep for 1 second } return NULL; } int main() { int ret; struct itimerval timer; ret = pthread_create(&thread, NULL, thread_one_func, NULL); if(ret != 0) { perror("pthread_create error"); return -1; } // set the timer timer.it_value.tv_sec = 5; timer.it_value.tv_usec = 0; timer.it_interval.tv_sec = 5; timer.it_interval.tv_usec = 0; signal(SIGALRM, kill_son_thread); // register a signal for timer action setitimer(ITIMER_REAL, &timer, NULL); // start the timer while(should_loop) ; return 0; }运行结果:
可以看到,主线程大约5秒后干掉了子线程,然后结束了。
Q: pthread_exit不也可以退出线程么?
A: 是的。不用定时器,子线程5秒后自动退出,代码如下:
#include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sys/time.h> #include <sys/signal.h> #define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue)); #define PRINT_STR(str) printf(#str" is %s\n", (str)); #define FOR_EVER() { while(1) ; } pthread_t thread; int should_loop = 1; void *thread_one_func(void *args) { int i = 1; while (i > 0) { printf("thread: loop %d\n", i++); sleep(1); // sleep for 1 second if(i == 6) { should_loop = 0; printf("[Son thread]: end...\n"); pthread_exit(NULL); } } return NULL; } int main() { int ret; ret = pthread_create(&thread, NULL, thread_one_func, NULL); if(ret != 0) { perror("pthread_create error"); return -1; } while(should_loop) ; printf("[Main thread]: end...\n"); return 0; }运行结果:
Q: 还有个函数,pthread_join的作用是什么?
A: 它的作用是等待指定线程执行结束。它实现了线程之间的同步。
#include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sys/time.h> #include <sys/signal.h> #define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue)); #define PRINT_STR(str) printf(#str" is %s\n", (str)); #define FOR_EVER() { while(1) ; } pthread_t thread; int should_loop = 1; void *thread_one_func(void *args) { int i = 1; while (i > 0) { printf("thread: loop %d\n", i++); sleep(1); // sleep for 1 second if(i == 6) { should_loop = 0; pthread_exit(NULL); } } return NULL; } int main() { int ret; ret = pthread_create(&thread, NULL, thread_one_func, NULL); if(ret != 0) { perror("pthread_create error"); return -1; } pthread_join(thread, NULL); // wait for the son thread's end printf("[Son thread]: end...\n"); while(should_loop) ; printf("[Main thread]: end...\n"); return 0; }运行结果:
Q: 上面的情形,主线程需要等待子线程结束,如果主线程不必等待子线程结束,子线程为主线程提供必要的数据,二者同步运行,如何处理?
A: 那么,可以使用互斥体、信号量等。
#include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sys/time.h> #include <sys/signal.h> #define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue)); #define PRINT_STR(str) printf(#str" is %s\n", (str)); #define FOR_EVER() { while(1) ; } pthread_t thread; int should_loop = 1; pthread_mutex_t mutex; int data[3]; void *thread_one_func(void *args) { int i = 1; while (i > 0) { pthread_mutex_lock(&mutex); data[0] = i; data[1] = i + 1; data[2] = i + 2; ++i; sleep(1); pthread_mutex_unlock(&mutex); } return NULL; } int main() { int ret; // create and init a mutex pthread_mutex_init(&mutex, NULL); ret = pthread_create(&thread, NULL, thread_one_func, NULL); if(ret != 0) { perror("pthread_create error"); return -1; } while(1) { pthread_mutex_lock(&mutex); if(data[0] > 3) { pthread_mutex_unlock(&mutex); break; } printf("[Main thread]: %d %d %d\n", data[0], data[1], data[2]); pthread_mutex_unlock(&mutex); sleep(1); // avoid the main thread running too fast, thanks wufangna ! } pthread_mutex_destroy(&mutex); printf("[Main thread]: end...\n"); return 0; }上面的代码,主线程从全局数据data中读取数据,子线程大约每1秒更新下data中的数据,当data[0]的值大于3的时候主线程退出。
运行结果:
Q: 还有种类型pthread_cond_t,它和pthread_mutex_t有什么区别?
A: 前者是在某种情况下设定的"互斥体", 后者可以当成无条件的互斥体;例子如下,
#include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <sys/time.h> #include <sys/signal.h> #define PRINT_D(intValue) printf(#intValue" is %d\n", (intValue)); #define PRINT_STR(str) printf(#str" is %s\n", (str)); #define FOR_EVER() { while(1) ; } pthread_t thread; int should_loop = 1; pthread_mutex_t mutex; int data[3]; pthread_cond_t cond; void *thread_one_func(void *args) { int i = 1; while (i > 0) { pthread_mutex_lock(&mutex); data[0] = i; data[1] = i + 1; data[2] = i + 2; if(data[0] % 2 == 0) pthread_cond_signal(&cond); ++i; sleep(1); pthread_mutex_unlock(&mutex); } return NULL; } int main() { int ret; // create and init a mutex pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); ret = pthread_create(&thread, NULL, thread_one_func, NULL); if(ret != 0) { perror("pthread_create error"); return -1; } while(1) { pthread_mutex_lock(&mutex); if(data[0] > 6) { pthread_mutex_unlock(&mutex); break; } pthread_cond_wait(&cond, &mutex); printf("[Main thread]: %d %d %d\n", data[0], data[1], data[2]); pthread_mutex_unlock(&mutex); } pthread_cond_destroy(&cond); pthread_mutex_destroy(&mutex); printf("[Main thread]: end...\n"); return 0; }上面的代码,主线程当发现data[0]大于6时就退出;小于6的时候,等待cond的状态变化;子线程会更新data数组中的数值,且当data[0]是偶数的时候就激活等待cond的线程(主线程),二者实现同步和互斥。
运行效果:
对于同步互斥,semaphore也可以实现; sem_open, sem_wait等等是操作它的函数,这里不再一一介绍。
xichen
2012-5-19 15:46:26