Linux线程详解

一、线程概述

线程(Thread)是程序执行流的最小单位,它是进程内的一个执行单元。一个进程可以有多个线程,每个线程都可以运行在单独的CPU上。与进程不同,线程共享进程内的一些资源,如内存、文件等。

线程的创建和销毁比进程要方便快捷,因为它们不需要分配独立的地址空间。因此,线程适合于需要高并发的场景,在网络编程、多媒体应用、数据库等应用中都有非常广泛的应用。

二、线程的创建

在Linux下,线程是通过调用pthread_create函数创建的。该函数的原型如下:

#include <pthread.h>

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

其中,thread 是指向pthread_t类型的指针,是线程的标识符,用于启动、暂停、恢复和删除线程;attr 是指向 pthread_attr_t 类型的指针,用于设置线程属性,默认可以传 NULL;start_routine 是指向函数的指针,这个函数是线程运行的起点;arg 是传递给线程的参数,可以是单个变量、结构体或指针。

下面的代码演示了一个简单的线程创建过程:

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

void *thread_func(void *arg) { 
    printf("Thread running\n");
    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    pthread_create(&thread, NULL, thread_func, NULL);
    pthread_join(thread, NULL);
    return 0;
}

在这个例子中,线程运行的起点是 thread_func 函数,在该函数内部打印字符串 “Thread running”。在主函数中,调用 pthread_create 创建线程并传入 thread_func 函数,等待线程执行完成后,调用 pthread_join 函数进行回收。

三、线程同步

在多线程环境下,由于多个线程可以同时访问共享资源,因此需要同步操作以避免冲突。

Linux提供了多种同步机制,下面介绍其中两种:互斥锁和条件变量。

互斥锁

互斥锁(mutex)可以用来保证共享资源的互斥访问。当一个线程获取了互斥锁,其他线程需要等待它释放锁后才能执行相应的操作。Linux下的互斥锁实现在pthread.h头文件中,它的主要函数包括:

  • pthread_mutex_init 初始化互斥锁
  • pthread_mutex_destroy 销毁互斥锁
  • pthread_mutex_lock 获取互斥锁
  • pthread_mutex_unlock 释放互斥锁

下面是一个使用互斥锁进行同步的例子:

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

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;

void *thread_func(void *arg) { 
    pthread_mutex_lock(&lock);
    counter++;
    printf("Thread ID: %d incremented counter to %d\n", (int)pthread_self(), counter);
    pthread_mutex_unlock(&lock);
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[10];
    for(int i = 0; i < 10; i++) {
        pthread_create(&threads[i], NULL, thread_func, NULL);
    }
    for(int i = 0; i < 10; i++) {
        pthread_join(threads[i], NULL);
    }
    printf("Final value of counter is %d\n", counter);
    return 0;
}

在这个例子中,10个线程共享变量counter,每个线程执行后将counter加1,并打印当前线程的ID和counter的值。由于多线程环境下,对共享变量的操作需要同步,因此在每个线程函数内部使用pthread_mutex_lock和pthread_mutex_unlock进行互斥访问。

条件变量

条件变量(condition variable)是一种同步机制,它能够使一个线程等待另一个线程的通知。线程在条件变量上等待,直到另一个线程使用pthread_cond_signal或pthread_cond_broadcast函数通知它可以继续执行。Linux下的条件变量实现在pthread.h头文件中,它的主要函数包括:

  • pthread_cond_init 初始化条件变量
  • pthread_cond_destroy 销毁条件变量
  • pthread_cond_wait 等待条件变量
  • pthread_cond_signal 唤醒一个线程
  • pthread_cond_broadcast 唤醒所有线程

下面是一个使用条件变量进行同步的例子:

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

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
int waiting = 1;

void *thread_func(void *arg) { 
    pthread_mutex_lock(&lock);
    while(waiting) {
        pthread_cond_wait(&cond, &lock);
    }
    printf("Thread ID: %d continuing...\n", (int)pthread_self());
    pthread_mutex_unlock(&lock);
    pthread_exit(NULL);
}

int main() {
    pthread_t threads[5];
    for(int i = 0; i < 5; i++) {
        pthread_create(&threads[i], NULL, thread_func, NULL);
    }
    sleep(1);
    printf("Wake up threads ...\n");
    pthread_mutex_lock(&lock);
    waiting = 0;
    pthread_cond_broadcast(&cond);
    pthread_mutex_unlock(&lock);
    for(int i = 0; i < 5; i++) {
        pthread_join(threads[i], NULL);
    }
    return 0;
}

在这个例子中,5个线程在条件变量上等待,直到主线程调用pthread_cond_broadcast函数释放条件变量并唤醒它们。线程运行的起点是thread_func函数,在该函数内部调用pthread_cond_wait等待条件变量,在条件变量被唤醒后,线程继续执行并打印当前线程的ID。

四、线程的销毁

在不需要某个线程继续执行的时候,需要销毁它以释放内存等资源。Linux下,使用pthread_cancel函数可以向一个线程发送取消请求,这个请求是异步执行的,即立即返回,线程本身仍然继续执行。另外,还可以使用pthread_join函数等待线程执行完成后回收它的资源。

下面是一个使用pthread_cancel函数取消线程的例子:

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

void *thread_func(void *arg) { 
    int i = 0;
    while(1) {
        printf("Thread ID: %d count %d\n", (int)pthread_self(), i++);
    }
    pthread_exit(NULL);
}

int main() {
    pthread_t thread;
    pthread_create(&thread, NULL, thread_func, NULL);
    sleep(3);
    pthread_cancel(thread);
    pthread_join(thread, NULL);
    printf("Thread canceled\n");
    return 0;
}

在这个例子中,创建了一个线程,不断循环打印当前线程ID和计数器的值。在主程序中,通过调用pthread_cancel函数向线程发送取消请求,并使用pthread_join函数等待线程完成后回收资源。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/205875.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-07 17:47
下一篇 2024-12-07 17:47

相关推荐

  • Python线程等待指南

    本文将从多个方面详细讲解Python线程等待的相关知识。 一、等待线程结束 在多线程编程中,经常需要等待线程执行完毕再进行下一步操作。可以使用join()方法实现等待线程执行完毕再…

    编程 2025-04-29
  • Python两个线程交替打印1到100

    这篇文章的主题是关于Python多线程的应用。我们将会通过实际的代码,学习如何使用Python两个线程交替打印1到100。 一、创建线程 在Python中,我们可以使用Thread…

    编程 2025-04-28
  • ROS线程发布消息异常解决方法

    针对ROS线程发布消息异常问题,我们可以从以下几个方面进行分析和解决。 一、检查ROS代码是否正确 首先,我们需要检查ROS代码是否正确。可能会出现的问题包括: 是否正确初始化RO…

    编程 2025-04-28
  • Python线程池并发爬虫

    Python线程池并发爬虫是实现多线程爬取数据的常用技术之一,可以在一定程度上提高爬取效率和数据处理能力。本文将从多个方面对Python线程池并发爬虫做详细的阐述,包括线程池的实现…

    编程 2025-04-27
  • 如何在Linux中添加用户并修改配置文件

    本文将从多个方面详细介绍在Linux系统下如何添加新用户并修改配置文件 一、添加新用户 在Linux系统下创建新用户非常简单,只需使用adduser命令即可。使用以下命令添加新用户…

    编程 2025-04-27
  • 如何解决linux jar包 invalid or corrupt jarfile问题

    对于许多开发人员和系统管理员在Linux环境下使用Java开发过程中遇到的一个常见的问题是 invalid or corrupt jarfile(无效或损坏的jar文件)错误。当您…

    编程 2025-04-27
  • 线程池中的一个线程异常了会被怎么处理

    本文将从以下几个方面对线程池中的一个线程异常了会被怎么处理进行详细阐述:异常的类型、如何捕获异常、异常的处理方式。 一、异常的类型 在线程池中,可以出现多种类型的异常,例如线程执行…

    编程 2025-04-27
  • 在Linux上安装JRE并配置环境变量

    本文将从以下几个方面为您详细阐述如何在Linux系统上,通过自己账户安装JRE,并且配置环境变量。 一、安装JRE 在进行安装前,我们需要下载JRE的安装包并解压,可以从官方网站下…

    编程 2025-04-27
  • GTKAM:Linux下的照片管理器

    GTKAM是用于Linux操作系统的一款照片管理器,它支持多种相机及存储设备,并提供了一系列强大的工具,让用户可以方便地浏览、管理、编辑和导出照片。本文将从多个方面对GTKAM进行…

    编程 2025-04-27
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25

发表回复

登录后才能评论