linux下c语言的多线程编程

关于Linux下C语言的多线程编程,可以看做是单CPU多任务或并发执行的模式,使用线程可以有效地提高应用程序的执行效率和利用率,对于高并发场景下的服务端应用尤为重要。下面是具体的攻略:

一、线程的创建和销毁

Linux下的多线程编程主要用到pthread库,使用pthread库需要包含< pthread.h >头文件。

  1. 可以使用pthread_create函数来创建一个新线程,其原型为:
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
    其中thread是输出参数,用于获取新线程的ID;attr通常设置为NULL,表示使用系统默认的属性;start_routine是函数指针,指向线程执行的函数入口;arg是传入start_routine函数的参数。

  2. 线程的销毁可以使用pthread_join函数,其原型为:
    int pthread_join(pthread_t thread, void **retval);
    其中thread是需要等待的线程ID;retval是线程退出时的返回值。

二、线程的同步

多线程编程中,线程间的同步和互斥非常重要,可以使用以下几种方式来实现:

  1. 互斥锁:使用互斥锁(mutex)可以使得多个线程互斥地访问共享资源,使用pthread库中的pthread_mutex_init、pthread_mutex_lock、pthread_mutex_unlock和pthread_mutex_destroy函数可以对互斥锁进行初始化、加锁、解锁和销毁等操作。

  2. 读写锁:读写锁(read-write lock)允许多个线程同时读取共享资源,但只允许一个线程对共享资源进行写操作,使用pthread库中的pthread_rwlock_init、pthread_rwlock_rdlock、pthread_rwlock_wrlock、pthread_rwlock_unlock和pthread_rwlock_destroy函数可以对读写锁进行初始化、加锁、解锁和销毁等操作。

  3. 条件变量:条件变量(condition variable)允许线程进入休眠状态,等待另一个线程通知该条件已经被满足,使用pthread库中的pthread_cond_init、pthread_cond_wait、pthread_cond_signal、pthread_cond_broadcast和pthread_cond_destroy函数可以对条件变量进行初始化、等待、通知、广播和销毁等操作。

三、示例说明

下面给出两个例子来说明多线程编程的应用。

1. 使用线程来实现并发处理任务

假设有一个任务队列,不断地有新的任务需要处理,可以使用一个生产者线程来不断地往任务队列中添加任务,同时使用多个消费者线程来并发地处理任务。

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

#define NUM_THREADS  5

pthread_t threads[NUM_THREADS];

pthread_mutex_t task_mutex;
int task_queue[100];
int task_count = 0;

void* producer_thread(void *arg)
{
    int i;
    while (1) {
        int task = rand() % 1000;
        pthread_mutex_lock(&task_mutex);
        task_queue[task_count++] = task;
        printf("producer task %d\n", task);
        pthread_mutex_unlock(&task_mutex);
        sleep(1);
    }
    return NULL;
}

void* consumer_thread(void *arg)
{
    while (1) {
        printf("consumer wait for task...\n");
        pthread_mutex_lock(&task_mutex);
        while (task_count == 0) {
            pthread_mutex_unlock(&task_mutex);
            sleep(1);
            pthread_mutex_lock(&task_mutex);
        }
        int task = task_queue[--task_count];
        printf("consumer task %d\n", task);
        pthread_mutex_unlock(&task_mutex);
        sleep(1);
    }
    return NULL;
}

int main()
{
    int i, rc;
    pthread_mutex_init(&task_mutex, NULL);
    srand(time(NULL));
    for (i = 0; i < NUM_THREADS; i++) {
        if (i == 0) {
            rc = pthread_create(&threads[i], NULL, producer_thread, NULL);
        } else {
            rc = pthread_create(&threads[i], NULL, consumer_thread, NULL);
        }
        if (rc) {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
    }
    pthread_exit(NULL);
}

在上面的代码中,使用一个producer线程来不断地往任务队列中添加任务,使用多个consumer线程来并发地从任务队列中获取任务并处理任务,使用pthread_mutex_lock和pthread_mutex_unlock来实现任务队列的互斥访问。

2. 使用线程来提高排序算法的效率

假设有一个需要排序的数组,可以使用多个线程来并发地进行排序操作,提高排序的效率。

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

#define NUM_THREADS  4
#define ARRAY_SIZE   100
#define MAX_VALUE    1000

pthread_t threads[NUM_THREADS];

typedef struct {
    int *data;
    int start;
    int end;
} sort_arg_t;

void* sort_thread(void *arg)
{
    sort_arg_t *a = (sort_arg_t *)arg;
    int *data = a->data;
    int start = a->start;
    int end = a->end;
    int i, j, t;
    for (i = start; i < end; i++) {
        for (j = i + 1; j < end; j++) {
            if (data[i] > data[j]) {
                t = data[i];
                data[i] = data[j];
                data[j] = t;
            }
        }
    }
    return NULL;
}

void merge_array(int *data, int a, int b, int c)
{
    int i = a, j = b, k = 0;
    int *tmp = (int *)malloc(sizeof(int) * (c - a));
    while (i < b && j < c) {
        if (data[i] < data[j]) {
            tmp[k++] = data[i++];
        } else {
            tmp[k++] = data[j++];
        }
    }
    while (i < b) {
        tmp[k++] = data[i++];
    }
    while (j < c) {
        tmp[k++] = data[j++];
    }
    for (i = a, k = 0; i < c; i++, k++) {
        data[i] = tmp[k];
    }
    free(tmp);
}

void merge_sort(int *data, int start, int end)
{
    if (start + 1 < end) {
        int mid = (start + end) / 2;
        merge_sort(data, start, mid);
        merge_sort(data, mid, end);
        merge_array(data, start, mid, end);
    }
}

int main()
{
    int i, rc;
    int data[ARRAY_SIZE];
    srand(time(NULL));
    for (i = 0; i < ARRAY_SIZE; i++) {
        data[i] = rand() % MAX_VALUE;
    }
    merge_sort(data, 0, ARRAY_SIZE);
    printf("sorted data:\n");
    for (i = 0; i < ARRAY_SIZE; i++) {
        printf("%d ", data[i]);
    }
    printf("\n");

    sort_arg_t arg[NUM_THREADS];
    for (i = 0; i < NUM_THREADS; i++) {
        arg[i].data = data;
        arg[i].start = i * ARRAY_SIZE / NUM_THREADS;
        arg[i].end = (i + 1) * ARRAY_SIZE / NUM_THREADS;
        rc = pthread_create(&threads[i], NULL, sort_thread, &arg[i]);
        if (rc) {
            printf("ERROR; return code from pthread_create() is %d\n", rc);
            exit(-1);
        }
    }
    for (i = 0; i < NUM_THREADS; i++) {
        rc = pthread_join(threads[i], NULL);
        if (rc) {
            printf("ERROR; return code from pthread_join() is %d\n", rc);
            exit(-1);
        }
    }
    printf("sorted data (multi-thread):\n");
    for (i = 0; i < ARRAY_SIZE; i++) {
        printf("%d ", data[i]);
    }
    printf("\n");

    return 0;
}

在上面的代码中,使用多个线程来并发地进行排序操作,先使用单线程进行对排序算法的测试,然后使用多线程的方式来进行排序操作,使用pthread_create和pthread_join来实现线程的创建和销毁操作,使用sort_arg_t结构体来传递线程的参数,使用merge_sort来进行排序操作,线程中的sort_thread函数用来对部分数据进行排序操作。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:linux下c语言的多线程编程 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • JAVA线上常见问题排查手段(小结)

    我来为您详细讲解“JAVA线上常见问题排查手段(小结)”的完整攻略。 标题 JAVA线上常见问题排查手段(小结) 简介 在JAVA应用程序运行过程中,可能会出现各种各样的问题,例如性能瓶颈、内存泄漏、代码逻辑错误等,这些问题会影响到应用程序的运行效率和稳定性,也会导致用户体验不佳。本文将介绍一些JAVA线上常见问题排查手段,以帮助开发者快速定位和解决问题。 …

    多线程 2023年5月17日
    00
  • 易语言启用多线程方法实例分享

    易语言启用多线程方法实例分享 多线程编程是一种常见的编程模式,易语言作为一种可视化编程语言,支持使用多线程方式来实现异步处理,提高程序的性能和响应速度。本文将分享易语言启用多线程的实现方法和示例,帮助读者了解多线程编程的基本原理和使用方法。 多线程编程基本原理 在多线程编程中,程序将同时执行多个线程,每个线程独立执行不同的任务。线程的执行顺序和时间不确定,程…

    多线程 2023年5月17日
    00
  • 浅谈Java获得多线程的返回结果方式(3种)

    浅谈Java获得多线程的返回结果方式(3种) 在Java中,多线程编程是经常遇到的问题。其中一个常见的问题是如何从多线程中获得返回结果。本文将讨论三种解决方案。 方案1:使用Future接口 Future接口可以用来获取异步操作的结果。它提供了一种异步获取结果的方式,当异步操作完成时,可以通过Future接口得到结果。在Java中可以通过FutureTask…

    多线程 2023年5月16日
    00
  • java多线程实现文件下载

    实现文件下载的过程中,可以通过使用多线程技术来提高文件下载速度。在Java中,可以利用Java多线程机制实现文件下载。下面是一个具体的实现攻略。 1. 多线程下载原理 多线程下载的原理是将一个大文件划分为若干个较小的文件块,每个线程分别下载不同的文件块。通过多个线程同时下载不同的文件块,可以加快整个文件的下载速度。同时,在下载过程中还需要考虑线程的安全性问题…

    多线程 2023年5月16日
    00
  • 详解超线程、多核、多处理器的区别

    详解超线程、多核、多处理器的区别 在讨论超线程、多核、多处理器之间的区别之前,我们需要了解计算机中的两个重要概念:线程和核心。 线程:计算机中执行任务的最小单位,是CPU执行指令和操作的基本单元。每个CPU核心可以同时执行多个线程。 核心:计算机的核心是处理器中的一个物理处理单元,它可用于执行任何指令并完成基本的算术或逻辑运算。 现在让我们深入了解超线程、多…

    多线程 2023年5月17日
    00
  • Java并发编程Semaphore计数信号量详解

    Java并发编程Semaphore计数信号量详解 介绍 Semaphore(信号量)是一个经典的并发编程工具,被广泛应用于各种应用场景,如资源池、限流等。Semaphore 给予我们对并发调度这个宏观的掌控权。 在 Java 5 中,Semaphore 正式被纳入了 Java 并发包,并成为了并发编程中一个必不可少的类。Semaphore 是一个计数信号量,…

    多线程 2023年5月16日
    00
  • java多线程下载实例详解

    Java多线程下载实例详解 本文将介绍Java多线程下载的实现方法和步骤,并提供两个示例说明。 实现步骤 Java多线程下载的实现步骤如下: 获取需要下载的文件的URL地址。 创建多个线程,每个线程负责下载文件的不同部分。 启动多个线程,通过HTTP请求下载各自负责的文件部分。 合并下载完成的文件部分。 完成文件下载。 示例一:Java多线程文件下载 以下示…

    多线程 2023年5月17日
    00
  • node 使用 async 控制并发的方法

    一、什么是 Node.js? Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Node.js 采用了事件驱动、非阻塞 I/O(input/output)模型,使其轻量又高效。 二、为什么使用 async 控制并发? 在编写 Node.js 程序时,往往需要同时进行多个操作,比如同时读取多个文件、同时请求多个接口等等。如…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部