Linux的多任务编程-线程
Linux操作系统很早就具备这些多进程功能了.但有时人们认为用fork()来创建一个新进程的代价还是太大,如在Web服务器中,通常采取的多进程方案是一旦接收到访问请求后,即创建一个新的进程,由该进程执行任务,当任务执行完毕后,该进程退出.如果有大量的请求在很短的时间中频繁的访问该服务器,那么服务器耗费在创建进程,销毁进程中的机时便十分可观.如果能用线程来完成这个工作,则情况会好很多.
线程的出现使得程序有了多个控制流程,能够在单进程的环境中执行多个任务.有了线程之后,一个进程就能够做不止一件事情.这使得程序复杂化了,但是这样做有很多优点:
#include <pthread.h> int pthread_equal (pthread_t tid1, pthread_t tid2);与getpid函数类似,在线程中获取自身的线程ID的函数是:
#include <pthread.h> pthread_t pthread_self (void);上面给出的这两个函数都有一个前缀"pthread_".事实上,与线程有关的函数库构成了一个完整的系列,绝大多数函数的名字都是以"pthread_"打头的.为了使用这些函数库,首先必须包含头文件<pthread.h>,其次在链接这些线程函数库时要使用编译器命令的"-pthread"选项.
#include <pthread.h> int pthread_create (pthread_t *thread, pthread_attr_t *attr, void *(*start_rtn)(void), void *restrict arg);
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> void print_ids (const char *s) { pid_t pid; pthread_t tid; pid = getpid(); tid = pthread_self(); printf("%s pid %u tid %u (0x%x)\n", s,\ (unsigned int)pid,(unsigned int)tid,\ (unsigned int)tid); } void *thread_func(void *arg) { print_ids("new thread: "); printf("thread param is :%d\n",*(int *)arg); return NULL; } int main(void) { int err; pthread_t newtid; int myarg; myarg=1; err = pthread_create (&newtid, NULL, thread_func, &myarg); if (err != 0) { perror("create thread error"); exit(1); } print_ids("main thread:"); sleep(1); exit(0); }
单个线程可以通过三种方式退出执行:
#include <pthread.h> void pthread_exit (void *rval_ptr); int pthread_join (pthread_t thread , void **rval_ptr);
#include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread1(void *arg) { printf("thread1 returning\n"); return ((void *)1); } void *thread2(void *arg) { printf("thread2 exiting\n"); pthread_exit ((void *)2); } int main(void) { int err; pthread_t tid1,tid2; void *tret; err = pthread_create (&tid1, NULL, thread1, NULL); if (err != 0) { perror("create thread1 error"); exit(1); } err = pthread_create (&tid2, NULL, thread2, NULL); if (err != 0) { perror("create thread2 error"); exit(1); } err = pthread_join(tid1, &tret); if (err != 0) { perror("join thread1 error"); exit(1); } printf("The exit code of thread1 :%d\n",(int)tret); err = pthread_join(tid2, &tret); if (err != 0) { perror("join thread2 error"); exit(1); } printf("The exit code of thread2 :%d\n",(int)tret); exit(0); }
#include <pthread.h>
int pthread_calcel ( pthread_ t tid);
该函数并不像pthread_exit函数那样,强迫线程退出,而只是提出一个要求,至于被要求的线程,既可以接受请求退出执行,也可以忽略该请求继续执行.这个问题涉及到线程属性的设置,在后面我们会详细讲解.#include <pthread.h> int pthread_attr_init (pthread_attr_t *attr); int pthread_attr_destroy (pthread_attr_t *attr);
#include <pthread.h> int pthread_attr_getdetachstate ( pthread_attr_t *attr, int *detachstate ); int pthread_attr_setdetachstate ( pthread_attr_t *attr, int detachstate );
#include <pthread.h> int pthread_attr_getscope( pthread_attr_t *tattr, int *scope ); int pthread_attr_setscope( pthread_attr_t *tattr, int scope );
#include <pthread.h> int pthread_attr_getstacksize( pthread_attr_t *tattr, size_t *size ); int pthread_attr_setstacksize( pthread_attr_t *tattr, int size );
#include <pthread.h> int pthread_attr_getschedpolicy( pthread_attr_t *tattr, int *policy ); int pthread_attr_setschedpolicy( pthread_attr_t *tattr, int policy );
#include <pthread.h> int pthread_getconcurrency( void ); int pthread_setconcurrency( int new_level );
#include <stdio.h> #include <stdlib.h> #include <pthread.h> void *thread1() { printf("this is thread1.\n"); sleep(1); printf("thread1 return\n"); } /*线程2*/ void *thread2() { printf("this is thread2.\n"); sleep(2); printf("thread2 exiting\n"); pthread_exit (0); } int main(void) { int err; pthread_t tid1,tid2; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); err = pthread_create (&tid1, &attr, thread1, NULL); if (err != 0) { perror("create thread1 error"); exit(1); } err = pthread_create (&tid2, NULL, thread2, NULL); if (err != 0) { perror("create thread2 error"); exit(1); } err = pthread_join(tid1, NULL); if (err != 0) { printf("can`t join thread1\n "); } err = pthread_join(tid2, NULL); if (err != 0) { perror("join thread2 error"); exit(1); } pthread_attr_destroy(&attr); exit(0); }
#include <pthread.h> int pthread_setcancelstate (int state, int *oldstate);此函数把当前的可取消状态置为变量state,把原来的可取消状态存放在oldstate只想的内存单元中,若执行成功则返回0,否则返回错误编码.
#include <pthread.h> int pthread_setcanceltype (int type, int *oldtype);参数type的取值可以是PTHREAD_CANCEL_DEFERRED或PTHREAD_CANCEL_ASYNCHRONOUS,原来的值保存在oldstype中.
#include <pthread.h> int pthread_testcancel (void);该函数检查本线程是否处于"待取消"状态(已经收到pthread_cancel的信号,但还没有到达取消点),若可取消状态没有被取消,则线程执行取消动作,否则返回.
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h> void *thread1(void *arg) { int i, err, j; err = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); if (err != 0) { perror("Thread1 pthread_setcancelstate failed"); exit(EXIT_FAILURE); } err = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); if (err != 0) { perror("Thread1 pthread_setcanceltype failed"); exit(EXIT_FAILURE); } printf("thread1 is running\n"); for(i = 0; i < 5; i++) { printf("Thread1 is still running (%d)...\n", i); sleep(1); } pthread_exit((void *)2); } void *thread2(void *arg) { int i, err, j; err = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); if (err != 0) { perror("Thread2 pthread_setcancelstate failed"); exit(EXIT_FAILURE); } err = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); if (err != 0) { perror("Thread2 pthread_setcanceltype failed"); exit(EXIT_FAILURE); } printf("thread2 is running\n"); for(i = 0; i < 5; i++) { printf("Thread2 is still running (%d)...\n", i); sleep(1); } pthread_exit((void *)2); } int main() { int err; pthread_t tid1,tid2; void *thread_result; err = pthread_create(&tid1, NULL, thread1, NULL); if (err != 0) { perror("Thread1 creation failed"); exit(EXIT_FAILURE); } err = pthread_create(&tid2, NULL, thread2, NULL); if (err != 0) { perror("Thread2 creation failed"); exit(EXIT_FAILURE); } sleep(2); printf("Cancelling thread1 ...\n"); err = pthread_cancel(tid1); if (err != 0) { perror("Thread1 cancelation failed"); exit(EXIT_FAILURE); } printf("Cancelling thread2 ...\n"); err = pthread_cancel(tid2); if (err != 0) { perror("Thread2 cancelation failed"); exit(EXIT_FAILURE); } printf("Waiting for thread1 to finish...\n"); err = pthread_join(tid1, &thread_result); if (err != 0) { perror("Thread1 join failed"); exit(EXIT_FAILURE); } printf("The exit code of thread1 :%d\n",(int)thread_result); printf("Waiting for thread2 to finish...\n"); err = pthread_join(tid2, &thread_result); if (err != 0) { perror("Thread2 join failed"); exit(EXIT_FAILURE); } printf("The exit code of thread2 :%d\n",(int)thread_result); exit(EXIT_SUCCESS); }线程1和线程2创建后即交替运行,由于线程1为可取消状态,当它接收到pthread_cancel的请求时便立即退出了(返回值为-1),而线程2为不可取消状态,因而一直运行到pthread_exit才退出(返回值为2).在上面的例子中,线程1的取消点为sleep函数,下表是常见的取消点.