Linux系统编程-(pthread)线程的使用案例(分离属性、清理函数等)

简介: 这篇文章介绍Linux下线程的创建与基本使用案例,主要是案例代码为主;相关的函数详细介绍在上篇文章里已经介绍过了。

这篇文章介绍Linux下线程的创建与基本使用案例,主要是案例代码为主;相关的函数详细介绍在上篇文章里已经介绍过了。

1. 案例代码: 线程的创建

下面这份代码演示如何创建线程。在编译的时候需要加上-lpthread

函数原型:

#include <pthread.h>
int pthread_create
(
pthread_t *thread, 
const pthread_attr_t *attr,
void *(*start_routine) (void *), 
void *arg
);

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>

//[wbyq@wbyq linux_c]$ gcc app.c -lpthread

/*
线程工作函数
*/
void *thread_work_func(void *dev)
{
    int i;
    for(i=0;i<5;i++)
    {
        sleep(1);
        printf("子线程正在运行.%d \n",i);
    }
    //终止当前线程执行
    pthread_exit(NULL);
}

int main(int argc,char **argv)
{
    /*1. 创建子线程*/
    pthread_t thread_id;
    if(pthread_create(&thread_id,NULL,thread_work_func,NULL)!=0)
    {
        printf("子线程创建失败.\n");
        return -1;
    }
    /*2. 等待子线程结束-清理子线程的空间*/
    pthread_join(thread_id,NULL);//--wait
    printf("主线程正常终止.\n");
    return 0;
}

2. 如何接收子线程的返回值?

线程运行的时候默认是结合模式,也可以设置成分离模式,如果是默认的模式,在线程执行完毕后需要回收资源,顺便可以介绍子线程结束时,返回的状态值。

函数原型:

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

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>

//[wbyq@wbyq linux_c]$ gcc app.c -lpthread

/*
线程工作函数
*/
void *thread_work_func(void *dev)
{
    int i;
    for(i=0;i<5;i++)
    {
        sleep(1);
        printf("子线程正在运行.%d \n",i);
    }
    //终止当前线程执行
    pthread_exit("1234567890");
}

int main(int argc,char **argv)
{
    /*1. 创建子线程*/
    pthread_t thread_id;
    if(pthread_create(&thread_id,NULL,thread_work_func,NULL)!=0)
    {
        printf("子线程创建失败.\n");
        return -1;
    }
    /*2. 等待子线程结束-清理子线程的空间*/
    char *p;
    pthread_join(thread_id,&p);//--wait
    printf("主线程正常终止.子线的返回值:%s\n",p);
    return 0;
}

3. 设置线程的分离属性

默认情况下,子线程是结合模式,需要手动等待子线程结束,清理空间;子线程也支持设置为分离属性,在子线程运行结束后,自己清理空间,下面的例子就演示如何设置子线程为分离模式。

函数原型:

int pthread_detach(pthread_t thread);

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>

//[wbyq@wbyq linux_c]$ gcc app.c -lpthread

/*
线程工作函数
*/
void *thread_work_func(void *dev)
{
    int i;
    for(i=0;i<5;i++)
    {
        sleep(1);
        printf("子线程正在运行.%d \n",i);
    }
    //终止当前线程执行
    pthread_exit(NULL);
}

int main(int argc,char **argv)
{
    /*1. 创建子线程*/
    pthread_t thread_id;
    if(pthread_create(&thread_id,NULL,thread_work_func,NULL)!=0)
    {
        printf("子线程创建失败.\n");
        return -1;
    }
    /*2. 设置线程的分离属性*/
    pthread_detach(thread_id);
    while(1)
    {
        printf("主线程正在运行.\n");
        sleep(1);
    }
    return 0;
}

4. 注册线程的清理函数

线程清理函数,可以在线程退出时自动调用或者手动调用,用于清理一些需要释放的资源。

函数原型:

//注册
void pthread_cleanup_push(void (*routine)(void *),void *arg); 
//释放
void pthread_cleanup_pop(int execute);

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdlib.h>
#include <pthread.h>

//[wbyq@wbyq linux_c]$ gcc app.c -lpthread

//线程的清理工作函数
void thread_clear_work_func(void *dev)
{
    printf("线程的清理工作函数被调用.\n");
    /*
    做一些资源清理工作。
    比如: 释放malloc申请的空间,关闭打开的文件等等.
    */
}

/*
线程工作函数
*/
void *thread_work_func(void *dev)
{
    int i;
    //注册清理函数
    pthread_cleanup_push(thread_clear_work_func,NULL); 
    for(i=0;i<5;i++)
    {
        sleep(1);
        printf("子线程正在运行.%d \n",i);
    }

    //终止当前线程执行
    pthread_exit(NULL);
    
    //释放清理函数
    pthread_cleanup_pop(1); 
}

int main(int argc,char **argv)
{
    /*1. 创建子线程*/
    pthread_t thread_id;
    if(pthread_create(&thread_id,NULL,thread_work_func,NULL)!=0)
    {
        printf("子线程创建失败.\n");
        return -1;
    }
    /*2. 设置线程的分离属性*/
    pthread_detach(thread_id);
    
    sleep(3);
    //取消指定子线程结束
    pthread_cancel(thread_id);

    while(1)
    {
        printf("主线程正在运行.\n");
        sleep(1);
    }
    return 0;
}

5. 通过ulimit命令设置栈空间大小

pthread_create 创建线程时,若不指定分配堆栈大小,系统会分配默认值,查看默认值方法如下:

[root@tiny4412 ]#ulimit -s
10240

上面的10240单位是KB,也就是默认的线程栈空间大小为10M

也可以通过ulimit -a命令查看,其中的stack size也表示栈空间大小。

[root@tiny4412 ]#ulimit -a
-f: file size (blocks)             unlimited
-t: cpu time (seconds)             unlimited
-d: data seg size (kb)             unlimited
-s: stack size (kb)                10240
-c: core file size (blocks)        0
-m: resident set size (kb)         unlimited
-l: locked memory (kb)             64
-p: processes                      7512
-n: file descriptors               1024
-v: address space (kb)             unlimited
-w: locks                          unlimited
-e: scheduling priority            0
-r: real-time priority             0

设置栈空间大小: ulimit -s <栈空间大小>

[root@tiny4412 ]#ulimit -s 8192   //设置栈空间大小
[root@tiny4412 ]#ulimit -s        //查看栈空间大小
8192                          //大小为8M

注意: 栈空间设置只能在超级管理员用户权限下设置。

每个线程的栈空间都是独立的,如果栈空间溢出程序会出现段错误。如果一个进程有10个线程,那么分配的栈空间大小就是10*<每个线程栈大小>

例如:

int main(int argc,char **argv)
{
    char buff[1024*1024*10];  //在栈空间定义数组,如果超出了栈空间总大小程序会奔溃。
    printf("hello world!\n");
    return 0;
}
目录
相关文章
|
2天前
|
数据采集 存储 数据处理
Python中的多线程编程及其在数据处理中的应用
本文深入探讨了Python中多线程编程的概念、原理和实现方法,并详细介绍了其在数据处理领域的应用。通过对比单线程与多线程的性能差异,展示了多线程编程在提升程序运行效率方面的显著优势。文章还提供了实际案例,帮助读者更好地理解和掌握多线程编程技术。
|
6天前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
15天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
11天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
15天前
|
Java UED
Java中的多线程编程基础与实践
【10月更文挑战第35天】在Java的世界中,多线程是提升应用性能和响应性的利器。本文将深入浅出地介绍如何在Java中创建和管理线程,以及如何利用同步机制确保数据一致性。我们将从简单的“Hello, World!”线程示例出发,逐步探索线程池的高效使用,并讨论常见的多线程问题。无论你是Java新手还是希望深化理解,这篇文章都将为你打开多线程的大门。
|
15天前
|
安全 Java 编译器
Java多线程编程的陷阱与最佳实践####
【10月更文挑战第29天】 本文深入探讨了Java多线程编程中的常见陷阱,如竞态条件、死锁、内存一致性错误等,并通过实例分析揭示了这些陷阱的成因。同时,文章也分享了一系列最佳实践,包括使用volatile关键字、原子类、线程安全集合以及并发框架(如java.util.concurrent包下的工具类),帮助开发者有效避免多线程编程中的问题,提升应用的稳定性和性能。 ####
42 1
|
19天前
|
存储 设计模式 分布式计算
Java中的多线程编程:并发与并行的深度解析####
在当今软件开发领域,多线程编程已成为提升应用性能、响应速度及资源利用率的关键手段之一。本文将深入探讨Java平台上的多线程机制,从基础概念到高级应用,全面解析并发与并行编程的核心理念、实现方式及其在实际项目中的应用策略。不同于常规摘要的简洁概述,本文旨在通过详尽的技术剖析,为读者构建一个系统化的多线程知识框架,辅以生动实例,让抽象概念具体化,复杂问题简单化。 ####
|
10天前
|
监控 Linux
如何检查 Linux 内存使用量是否耗尽?这 5 个命令堪称绝了!
本文介绍了在Linux系统中检查内存使用情况的5个常用命令:`free`、`top`、`vmstat`、`pidstat` 和 `/proc/meminfo` 文件,帮助用户准确监控内存状态,确保系统稳定运行。
87 6
|
11天前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
46 3
|
11天前
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
35 2
下一篇
无影云桌面