[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