Linux pthread 线程 浅解

2023-12-14 14:48
文章标签 linux 线程 pthread 浅解

本文主要是介绍Linux pthread 线程 浅解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

线程

  1. 问题
    使用fork创建进程以执行新的任务,该方式的代价很高。

    解决办法:使用线程

  2. 什么是线程
    线程,是进程内部的一个控制序列。
    即使不使用线程,进程内部也有一个执行线程。

    类比:创建一个进程,类似于“克隆”一个家庭。
    该“家庭”与原来的家庭完全相同
    但是新“家庭”和原来的家庭完全独立。

        进程包含一个或多个线程。类似与一个家庭,包含一个或多个家庭成员。家庭内的各成员同时做各自的事情(父亲工作、母亲持家、小孩上学)而对于家庭外部的人来说,这个家庭同时在做多件事情。家庭内的每个成员,就是一个线程。各个家庭成员有自己的个人资源(线程有自己的局部变量)但是所有家庭成员都能共享这个家庭的资源:房子、汽车、家庭的公共资金。(同一个进程内的各个线程,能够共享整个进程的全局变量,除了线程的局部变量外,其他资源都共享)
    

    注意:单核处理器上,同一个时刻只能运行一个线程。
    但是对于用户而言,感觉如同同时执行了多个线程一样
    (各线程在单核CPU上切换,在一段时间内,同时执行了多个线程)

  3. 线程的优点、缺点
    优点: 创建线程比创建进程,开销要小。
    缺点: 1)多线程编程,需特别小心,很容易发生错误。
    2)多线程调试很困难。
    3)把一个任务划分为两部分,
    用两个线程在单处理器上运行时,不一定更快。
    除非能确定这两个部分能同时执行、且运行在多处理器上。

  4. 线程的应用场合
    1) 需要让用户感觉在同时做多件事情时,
    比如,处理文档的进程,一个线程处理用户编辑,一个线程同时统计用户的字数。

    2) 当一个应用程序,需要同时处理输入、计算、输出时,
    可开3个线程,分别处理输入、计算、输出。
    让用户感觉不到等待。

  5. 线程的使用
    1)线程的创建
    pthread_create
    原型:int pthread_create (
    pthread_t *thread,
    pthread_attr_t *attr,
    void (*start_routine)(void),
    void *arg);

    参数:thread, 指向新线程的标识符。
    通过该指针返回所创建线程的标识符。
    attr, 用来设置新线程的属性。
    一般取默认属性,即该参数取NULL
    start_routine, 该线程的处理函数
    该函数的返回类型和参数类型都是void*
    arg, 线程处理函数start_routine的参数

    功能:创建一个新线程,
    同时指定该线程的属性、执行函数、执行函数的参数
    通过参数1返回该线程的标识符。

    返回值:成功,返回0
    失败,返回错误代码
    注意:大部分pthread_开头的函数成功时返回0,失败时返回错误码(而不是-1)

    注意:使用fork创建进程后,进程 马上就启动,但是是和父进程同时执行fork之后后的代码。
    使用pthread_create创建线程后,新线程马上就启动,即执行对应的线程处理函数。

    2)线程的终止
    pthread_exit
    原型:void pthread_exit (void *retval)
    功能:在线程函数内部调用该函数。
    终止该线程,并通过参数retval返回一个指针。
    该指针不能指向该线程的局部变量。

    3)等待指定线程结[
    pthread_join
    功能:类似与进程中的waitpid
    等待指定的线程结束,并使参数指向该线程函数的返回值(用pthread_exit返回的值)
    原型:int pthread_join (pthread_t th,
    void ** thread_return);
    参数:th, 指定等待的线程
    thread_return, 指向该线程函数的返回值
    线程函数的返回值类型为void*,故该参数的类型为void**

    4)使用线程程序的编译
    (1) 编译时,定义宏_REENTRANT
    即: gcc -D_REENTRANT (#define REENTRANT)

           功能:告诉编译器,编译时需要可重入功能。即使得,在编译时,编译部分函数的可重入版本。(2) 编译时,指定线程库即: gcc -lpthread功能:使用系统默认的NPTL线程库, 即在默认路径中寻找库文件libpthread.so 默认路径为/usr/lib和/usr/local/lib当系统默认使用的不是NPTL线程库时(系统较老,2003年以前)指定:gcc  -L/usr/lib/nptl   -lpthread补充: -L 指定库文件所在的目录-l  指定库文件的名称(-lpthread ,指库文件名为libpthread.so)总结:一般使用如下形式即可gcc   -D_REENTRANT   -lpthread    mythread.c    -o   mythread  
    

    4)实例
    main1.c

    实例
    创建一个线程,并传递一个字符串
    在新线程中,把所传递的字符串打印出来,
    并把字符串转换为大写,再返回给主线程
    新线程结束后,在主线程中,把所返回的结果打印输出。

#ifdef FUNC_A                            void test_func(void)
{printf("world");
}  #else void test_func(void)
{printf("hello");
}#endif 

main1.c

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>int my_global;void* my_thread_handle(void *arg) 
{int val;val = *((int*)arg);printf("new thread begin, arg=%d\n", val);my_global += val;sleep(3);pthread_exit(&my_global);//  ≤ª‘Ÿ÷¥––printf("new thread end\n");
}int main(void)
{pthread_t  mythread;int arg;int ret;void *thread_return;arg = 100;my_global = 1000;printf("my_global=%d\n", my_global);printf("ready create thread...\n");ret = pthread_create(&mythread, 0, my_thread_handle, &arg);if (ret != 0) {printf("create thread failed!\n");exit(1);}printf("wait thread finished...\n");ret = pthread_join(mythread, &thread_return);if (ret != 0) {printf("pthread_join failed!\n");exit(1);}printf("wait thread end, return value is %d\n", *((int*)thread_return));printf("my_global=%d\n", my_global);printf("create thread finished!\n");
}

这篇关于Linux pthread 线程 浅解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/492948

相关文章

linux生产者,消费者问题

pthread_cond_wait() :用于阻塞当前线程,等待别的线程使用pthread_cond_signal()或pthread_cond_broadcast来唤醒它。 pthread_cond_wait() 必须与pthread_mutex 配套使用。pthread_cond_wait()函数一进入wait状态就会自动release mutex。当其他线程通过pthread

Linux 安装、配置Tomcat 的HTTPS

Linux 安装 、配置Tomcat的HTTPS 安装Tomcat 这里选择的是 tomcat 10.X ,需要Java 11及更高版本 Binary Distributions ->Core->选择 tar.gz包 下载、上传到内网服务器 /opt 目录tar -xzf 解压将解压的根目录改名为 tomat-10 并移动到 /opt 下, 形成个人习惯的路径 /opt/tomcat-10

RedHat运维-Linux文本操作基础-AWK进阶

你不用整理,跟着敲一遍,有个印象,然后把它保存到本地,以后要用再去看,如果有了新东西,你自个再添加。这是我参考牛客上的shell编程专项题,只不过换成了问答的方式而已。不用背,就算是我自己亲自敲,我现在好多也记不住。 1. 输出nowcoder.txt文件第5行的内容 2. 输出nowcoder.txt文件第6行的内容 3. 输出nowcoder.txt文件第7行的内容 4. 输出nowcode

【Linux进阶】UNIX体系结构分解——操作系统,内核,shell

1.什么是操作系统? 从严格意义上说,可将操作系统定义为一种软件,它控制计算机硬件资源,提供程序运行环境。我们通常将这种软件称为内核(kerel),因为它相对较小,而且位于环境的核心。  从广义上说,操作系统包括了内核和一些其他软件,这些软件使得计算机能够发挥作用,并使计算机具有自己的特生。这里所说的其他软件包括系统实用程序(system utility)、应用程序、shell以及公用函数库等

Windows/macOS/Linux 安装 Redis 和 Redis Desktop Manager 可视化工具

本文所有安装都在macOS High Sierra 10.13.4进行,Windows安装相对容易些,Linux安装与macOS类似,文中会做区分讲解 1. Redis安装 1.下载Redis https://redis.io/download 把下载的源码更名为redis-4.0.9-source,我喜欢跟maven、Tomcat放在一起,就放到/Users/zhan/Documents

Linux系统稳定性的奥秘:探究其背后的机制与哲学

在计算机操作系统的世界里,Linux以其卓越的稳定性和可靠性著称,成为服务器、嵌入式系统乃至个人电脑用户的首选。那么,是什么造就了Linux如此之高的稳定性呢?本文将深入解析Linux系统稳定性的几个关键因素,揭示其背后的技术哲学与实践。 1. 开源协作的力量Linux是一个开源项目,意味着任何人都可以查看、修改和贡献其源代码。这种开放性吸引了全球成千上万的开发者参与到内核的维护与优化中,形成了

Linux 下的Vim命令宝贝

vim 命令详解(转自:https://www.cnblogs.com/usergaojie/p/4583796.html) vi: Visual Interface 可视化接口 vim: VI iMproved VI增强版 全屏编辑器,模式化编辑器 vim模式: 编辑模式(命令模式)输入模式末行模式 模式转换: 编辑-->输入: i: 在当前光标所在字符的前面,转为输入模式

Linux和Mac分卷压缩

使用 zip 命令压缩文件 使用 zip 命令压缩文件,并结合 split 命令来分卷: zip - largefile | split -b 500k 举例: zip - ./tomcat.dmg |split -b 500k 上述命令将文件 largefile 压缩成 zip 包并分卷成不超过 500k 的文件,分解后文件名默认是 x* ,后缀为 2 位a-z 字母,如 aa、ab。

Linux文本三剑客sed

sed和awk grep就是查找文本当中的内容,最强大的功能就是使用扩展正则表达式 sed sed是一种流编辑器,一次处理一行内容。 如果只是展示,会放在缓冲区(模式空间),展示结束后,会从模式空间把结果删除 一行行处理,处理完当前行,才会处理下一行。直到文件的末尾。 sed的命令格式和操作选项: sed -e '操作符 ' -e '操作符' 文件1 文件2 -e表示可以跟多个操作

Linux中拷贝 cp命令中拷贝所有的写法详解

This text from: http://www.jb51.net/article/101641.htm 一、预备  cp就是拷贝,最简单的使用方式就是: cp oldfile newfile 但这样只能拷贝文件,不能拷贝目录,所以通常用: cp -r old/ new/ 那就会把old目录整个拷贝到new目录下。注意,不是把old目录里面的文件拷贝到new目录,