Linux C 编程——多线程

    xiaoxiao2021-03-25  134

    线程是计算机中独立运行的最小单位,运行时占用很少的系统资源。与多进程相比,多进程具有多进程不具备的一些优点,其最重要的是:对于多线程来说,其能够比多进程更加节省资源。

    1、线程创建

    在Linux中,新建的线程并不是在原先的进程中,而是系统通过一个系统调用clone()。该系统copy了一个和原先进程完全一样的进程,并在这个进程中执行线程函数。

    在Linux中,通过函数pthread_create()函数实现线程的创建:

    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);

    其中:

    thread表示的是一个pthread_t类型的指针;attr用于指定线程的一些属性;start_routine表示的是一个函数指针,该函数是线程调用函数;arg表示的是传递给线程调用函数的参数。

    当线程创建成功时,函数pthread_create()返回0,若返回值不为0则表示创建线程失败。对于线程的属性,则在结构体pthread_attr_t中定义。

    线程创建的过程如下所示:

    #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <malloc.h> void* thread(void *id){ pthread_t newthid; newthid = pthread_self(); printf("this is a new thread, thread ID is %u\n", newthid); return NULL; } int main(){ int num_thread = 5; pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread); printf("main thread, ID is %u\n", pthread_self()); for (int i = 0; i < num_thread; i++){ if (pthread_create(&pt[i], NULL, thread, NULL) != 0){ printf("thread create failed!\n"); return 1; } } sleep(2); free(pt); return 0; }

    在上述代码中,使用到了pthread_self()函数,该函数的作用是获取本线程的线程ID。在主函数中的sleep()用于将主进程处于等待状态,以让线程执行完成。最终的执行效果如下所示:

    那么,如何利用arg向子线程传递参数呢?其具体的实现如下所示:

    #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <malloc.h> void* thread(void *id){ pthread_t newthid; newthid = pthread_self(); int num = *(int *)id; printf("this is a new thread, thread ID is %u,id:%d\n", newthid, num); return NULL; } int main(){ //pthread_t thid; int num_thread = 5; pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread); int * id = (int *)malloc(sizeof(int) * num_thread); printf("main thread, ID is %u\n", pthread_self()); for (int i = 0; i < num_thread; i++){ id[i] = i; if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){ printf("thread create failed!\n"); return 1; } } sleep(2); free(pt); free(id); return 0; }

    其最终的执行效果如下图所示:

    如果在主进程提前结束,会出现什么情况呢?如下述的代码:

    #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <malloc.h> void* thread(void *id){ pthread_t newthid; newthid = pthread_self(); int num = *(int *)id; printf("this is a new thread, thread ID is %u,id:%d\n", newthid, num); sleep(2); printf("thread %u is done!\n", newthid); return NULL; } int main(){ //pthread_t thid; int num_thread = 5; pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread); int * id = (int *)malloc(sizeof(int) * num_thread); printf("main thread, ID is %u\n", pthread_self()); for (int i = 0; i < num_thread; i++){ id[i] = i; if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){ printf("thread create failed!\n"); return 1; } } //sleep(2); free(pt); free(id); return 0; }

    此时,主进程提前结束,进程会将资源回收,此时,线程都将退出执行,运行结果如下所示:

    2、线程挂起

    在上述的实现过程中,为了使得主线程能够等待每一个子线程执行完成后再退出,使用了free()函数,在Linux的多线程中,也可以使用pthread_join()函数用于等待其他线程,函数的具体形式为:

    int pthread_join(pthread_t thread, void **retval);

    函数pthread_join()用来等待一个线程的结束,其调用这将被挂起。

    一个线程仅允许一个线程使用pthread_join()等待它的终止。

    如需要在主线程中等待每一个子线程的结束,如下述代码所示:

    #include <stdio.h> #include <pthread.h> #include <unistd.h> #include <malloc.h> void* thread(void *id){ pthread_t newthid; newthid = pthread_self(); int num = *(int *)id; printf("this is a new thread, thread ID is %u,id:%d\n", newthid, num); free(3); printf("thread %u is done\n", newthid); return NULL; } int main(){ int num_thread = 5; pthread_t *pt = (pthread_t *)malloc(sizeof(pthread_t) * num_thread); int * id = (int *)malloc(sizeof(int) * num_thread); printf("main thread, ID is %u\n", pthread_self()); for (int i = 0; i < num_thread; i++){ id[i] = i; if (pthread_create(&pt[i], NULL, thread, &id[i]) != 0){ printf("thread create failed!\n"); return 1; } } for (int i = 0; i < num_thread; i++){ pthread_join(pt[i], NULL); } free(pt); free(id); return 0; }

    最终的执行效果如下所示:

    注:在编译的时候需要链接libpthread.a: g++ xx.cc -lpthread -o xx

    转载请注明原文地址: https://ju.6miu.com/read-2229.html

    最新回复(0)