C语言多线程

yunfeitian 2020-07-05

什么是线程,线程的优点是什么

线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage)。 一个进程可以有很多线程,每条线程并行执行不同的任务。

线程可以提高应用程序在多核环境下处理诸如文件I/O或者socket I/O等会产生堵塞的情况的表现性能。在Unix系统中,一个进程包含很多东西,包括可执行程序以及一大堆的诸如文件描述符地址空间等资源。在很多情况下,完成相关任务的不同代码间需要交换数据。如果采用多进程的方式,那么通信就需要在用户空间和内核空间进行频繁的切换,开销很大。但是如果使用多线程的方式,因为可以使用共享的全局变量,所以线程间的通信(数据交换)变得非常高效。

Hello World(线程创建、结束、等待)

创建线程 pthread_create

线程创建函数包含四个变量,分别为: 1. 一个线程变量名,被创建线程的标识 2. 线程的属性指针,缺省为NULL即可 3. 被创建线程的程序代码 4. 程序代码的参数 For example: - pthread_t thrd1; - pthread_attr_t attr; - void thread_function(void argument); - char *some_argument;

pthread_create(&thrd1, NULL, (void *)&thread_function, (void *) &some_argument);

结束线程 pthread_exit

线程结束调用实例:pthread_exit(void *retval); //retval用于存放线程结束的退出状态

线程等待 pthread_join

pthread_create调用成功以后,新线程和老线程谁先执行,谁后执行用户是不知道的,这一块取决与操作系统对线程的调度,如果我们需要等待指定线程结束,需要使用pthread_join函数,这个函数实际上类似与多进程编程中的waitpid。 举个例子,以下假设 A 线程调用 pthread_join 试图去操作B线程,该函数将A线程阻塞,直到B线程退出,当B线程退出以后,A线程会收集B线程的返回码。 该函数包含两个参数:

  • pthread_t th //th是要等待结束的线程的标识
  • void **thread_return //指针thread_return指向的位置存放的是终止线程的返回状态。

调用实例:pthread_join(thrd1, NULL);

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void print_message_function (void *ptr);

int main()
{
    int tmp1, tmp2;
    void *retval;
    pthread_t thread1, thread2;
    char *message1 = "thread1";
    char *message2 = "thread2";

    int ret_thrd1, ret_thrd2;

    ret_thrd1 = pthread_create(&thread1, NULL, (void *)&print_message_function, (void *) message1);
    ret_thrd2 = pthread_create(&thread2, NULL, (void *)&print_message_function, (void *) message2);

    // 线程创建成功,返回0,失败返回失败号
    if (ret_thrd1 != 0) {
        printf("线程1创建失败\n");
    } else {
        printf("线程1创建成功\n");
    }

    if (ret_thrd2 != 0) {
        printf("线程2创建失败\n");
    } else {
        printf("线程2创建成功\n");
    }

    //同样,pthread_join的返回值成功为0
    tmp1 = pthread_join(thread1, &retval);
    // printf("thread1 return value(retval) is %d\n", (int)retval);
    printf("thread1 return value(tmp) is %d\n", tmp1);
    if (tmp1 != 0) {
        printf("cannot join with thread1\n");
    }
    printf("thread1 end\n");

    tmp2 = pthread_join(thread2, &retval);
    // printf("thread2 return value(retval) is %d\n", (int)retval);
    printf("thread2 return value(tmp) is %d\n", tmp1);
    if (tmp2 != 0) {
        printf("cannot join with thread2\n");
    }
    printf("thread2 end\n");

}

void print_message_function( void *ptr ) {
    int i = 0;
    for (i; i<5; i++) {
        sleep(3);
        printf("%s:%d\n", (char *)ptr, i);
    }
}

编译:

gcc duojincheng.c -o a -lpthread

如果不加-lpthread会报错:

/tmp/ccAfHhhZ.o:在函数‘main’中:
duojincheng.c:(.text+0x40):对‘pthread_create’未定义的引用
duojincheng.c:(.text+0x60):对‘pthread_create’未定义的引用
duojincheng.c:(.text+0xae):对‘pthread_join’未定义的引用
duojincheng.c:(.text+0xf2):对‘pthread_join’未定义的引用
collect2: error: ld returned 1 exit status

运行结果:

线程1创建成功
线程2创建成功
thread2:0
thread1:0
thread2:1
thread1:1
thread2:2
thread1:2
thread1:3
thread2:3
thread1:4
thread1 return value(tmp) is 0
thread1 end
thread2:4
thread2 return value(tmp) is 0
thread2 end

相关推荐