多线程入门

1 创建线程

下面的程序,我们可以用它来创建一个 POSIX 线程:

#include <pthread.h>
pthread_create (myThread, attr, start_routine, arg) 

在这里,pthread_create 创建一个新的线程,并让它可执行。下面是关于参数的说明:

|---------------|---------------------------------------------------------------------------|
| 参数 | 描述 |
| myThread | 指向线程标识符指针 |
| attr | 一个不透明的属性对象,可以被用来设置线程属性。您可以指定线程属性对象,也可以使用默认值 NULL。一般不需要关注,直接用NULL即可。 |
| start_routine | 线程运行函数起始地址,一旦线程被创建就会执行。函数内部就是子线程要运行的内容。 |
| arg | 运行函数的参数。必须通过把引用作为指针强制转换为 void 类型进行传递。如果没有传递参数,则使用 NULL。一般不需要关注,直接用NULL即可。 |

2 终止线程

终止线程可采用return NUL自动退出,也可以采用pthread_exit(NULL)强制退出。

3 示例

3.1 示例代码

该代码先执行main函数,然后创建了一个子线程thread_func,此时就存在两个线程,一个主线程,一个子线程。主线程运行一个计算(for循环i);子线程运行一个计算(for循环j)。最后主线程计算结束,子线程计算结束,子线程退出,主线程退出。整个程序结束。

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>

void *thread_func(void *arg)
{
    while (1)
    {
        for (int j = 0; j < 8; j++)
        {
            printf("sub:%d\n", j);
            usleep(10);
        }
        if(true/*线程不在使用了,可以退出*/){
            break;
        }else{
            //子线程后面还要使用
            usleep(10*1000);
            continue;//进入下个循环
        }
    }

    printf("sub thread return\n");
    return NULL;
}

int main()
{
    pthread_t tid;
    pthread_create(&tid, NULL, thread_func, NULL);
    for (int i = 0; i < 8; i++)
    {
        printf("main:%d\n", i);
        usleep(10);
    }
    pthread_join(tid, NULL);
    printf("main thread: all threads exit.\n");
    return 0;
}

3.2 编译

编译脚本为gcc Demo1.cpp -o Demo1 -lpthread。会生成名字为Demo的可执行程序。

Demo1.cpp中有使用线程技术,需要链接pthread库,即在编译脚本中添加-lpthread。

3.3 运行

./Demo1就是运行。运行逻辑示意图如下。

(1)主线程逻辑图:

(2)子线程逻辑图:

(3)CPU内核使用情况

总结: 如果只有一个主线程,则只能使用一个主线程内核,所以对于耗时较大的任务,使用多线程可以提高性能。

3.4 结果分析

可以看到结果,主线程main计算和子线程sub计算同时运行,节省了时间。

下面我们打印时间,进行对比。

(1)代码示例:

(2)编译运行结果

由此可见,使用一个子线程和一个主线程来进行2个计算,耗时较短,这是因为两个子线程分别持有一个CPU内核,并行进行计算。 缩短了总共时间。

另外创建线程也会耗时,如果计算耗时小于创建线程的耗时,则2个线程总共耗时不会优于一个线程,即总共耗时:创建线程耗时+计算1耗时+计算2耗时....。

3.5 源代码

3.3中统计时间的源代码。

Demo1.cpp

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>

#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
struct timeval time1, time2;

void *thread_func(void *arg)
{
    // 执行一些操作...
    int totalSub = 0;
    for (int j = 0; j < 80; j++)
    {
        int jk = ((j << 2) * 8) >> 2;
        int jl = ((j << 4) * 8) >> 4;
        totalSub = totalSub + jk + jl; // 计算1
        usleep(10 * 1000);
    }
    printf("sub total:%d\n", totalSub);
    printf("sub thread return\n");
    return NULL;
}

int main()
{
    double elapsed_time = 0.0;
    gettimeofday(&time1, NULL);

    pthread_t tid;
    pthread_create(&tid, NULL, thread_func, NULL);
    int totalmain = 0;
    for (int i = 0; i < 10; i++)
    {
        int ik = ((i << 2) * 8) >> 2;
        int il = ((i << 4) * 8) >> 4;
        totalmain = totalmain + il; // 计算2
        usleep(10 * 1000);
    }
    printf("main total:%d\n", totalmain);
    pthread_join(tid, NULL);
    gettimeofday(&time2, NULL);
    elapsed_time = (time2.tv_sec - time1.tv_sec) * 1000 + (time2.tv_usec - time1.tv_usec) / 1000;
    printf("Elapsed time: %lf(ms)\n", elapsed_time);
    printf("main thread: all threads exit.\n");
    return 0;
}

Demo2.cpp

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>

#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
struct timeval time1, time2;
int main()
{
    double elapsed_time = 0.0;
    gettimeofday(&time1, NULL);

    int totalSub = 0;
    int totalmain = 0;
    for (int j = 0; j < 80; j++)
    {
        int jk = ((j << 2) * 8) >> 2;
        int jl = ((j << 4) * 8) >> 4;
        totalSub = totalSub + jk + jl; // 计算1
        usleep(10*1000);
    }
    printf("main total:%d\n", totalSub);
    for (int i = 0; i < 10; i++)
    {
        int ik = ((i << 2) * 8) >> 2;
        int il = ((i << 4) * 8) >> 4;
        totalmain = totalmain + il; // 计算2
        usleep(10*1000);
    }
    printf("sub total:%d\n", totalSub);
    gettimeofday(&time2, NULL);
    elapsed_time = (time2.tv_sec - time1.tv_sec) * 1000 + (time2.tv_usec - time1.tv_usec)/1000;
    printf("Elapsed time: %lf(ms)\n", elapsed_time);
    return 0;
}
相关推荐
hvinsion1 分钟前
Python 敲电子木鱼,见机甲佛祖,修赛博真经
开发语言·python·pygame
zz.YE5 分钟前
【SpringMVC】REST 风格
java·后端·spring·restful
晚风_END21 分钟前
python|利用ffmpeg按顺序合并指定目录内的ts文件
开发语言·python·青少年编程·ffmpeg·vim·objective-c
web1309332039825 分钟前
[JAVA Web] 02_第二章 HTML&CSS
java·前端·html
两点王爷25 分钟前
Java项目中Oracle数据库开发过程中相关内容
java·sql·oracle
乄bluefox27 分钟前
关于easy-es对时间范围查询遇到的小bug
java·数据库·spring boot·elasticsearch·搜索引擎·bug
黑客呀27 分钟前
Go Web开发之Revel - 网页请求处理流程
开发语言·前端·web安全·golang·系统安全
和小潘一起学AI29 分钟前
c++基于过程
开发语言·c++
叫我阿呆就好了31 分钟前
C 实现植物大战僵尸(二)
c语言·开发语言
白宇横流学长31 分钟前
基于SpringBoot的垃圾分类系统设计与实现【源码+文档+部署讲解】
java·spring boot·后端