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日

相关文章

  • golang 限制同一时间的并发量操作

    下面是详细讲解“golang 限制同一时间的并发量操作”的完整攻略: 前置知识 在了解如何限制同一时间的并发量操作之前,我们需要先了解一些并发编程基础知识,包括 goroutine、channel、sync.WaitGroup 和 sync.Mutex。 goroutine:Go 语言的轻量级线程,可以在多个 goroutine 之间并发执行。 channe…

    多线程 2023年5月16日
    00
  • Linux下高并发socket最大连接数所受的各种限制(详解)

    Linux下高并发socket最大连接数所受的各种限制(详解) 在高并发socket编程过程中,最大连接数是一个非常重要的指标,通常情况下,我们希望在达到最大连接数时,能够有效地处理多余的连接请求。然而,在Linux系统下,最大连接数受到了多种限制,下面将对这些限制做详细的介绍。 1. 系统级别限制 1.1 somaxconn 在 Linux 系统中,有一个…

    多线程 2023年5月16日
    00
  • Java多线程之Interrupt中断线程详解

    Java多线程之Interrupt中断线程详解 在使用Java进行多线程编程时,经常需要控制线程的执行行为,比如暂停、终止、恢复线程等。这时我们就需要一个中断机制来实现我们的控制需求。Java中,通过Interrupt中断机制来实现对线程的中断控制。 中断线程的基本使用方法: 要中断一个Java线程,可以使用线程对象的interrupt()方法,其语法为: …

    多线程 2023年5月17日
    00
  • Nodejs实战心得之eventproxy模块控制并发

    Node.js实战心得之eventproxy模块控制并发 什么是eventproxy模块 eventproxy模块是Node.js中一个流行的第三方模块,用于控制异步并发。它通过定义事件与处理定制逻辑来解决异步嵌套问题,提供更好的可读性和可维护性。 使用eventproxy模块,可以避免回调函数嵌套过深,提高代码的可阅读性,同时也避免了异步操作中的“回调地狱…

    多线程 2023年5月16日
    00
  • Java使用Thread和Runnable的线程实现方法比较

    Java使用Thread和Runnable的线程实现方法比较 Java中的线程实现主要有两种方式:使用Thread类或使用Runnable接口。这两种方法都可以用于实现多线程编程,但使用方式和应用场景不同。在本文中,我们将比较这两种方法之间的异同点,并提供示例说明。 Thread类实现多线程 Java中的Thread类是一种封装了操作系统线程的类,使用这个类…

    多线程 2023年5月16日
    00
  • java多线程开启的三种方式你知道吗

    当我们需要在Java程序中同时执行多个任务时,可以使用多线程技术来提高程序的效率和响应能力。Java中开启多线程的方式有三种: 继承Thread类并重写run()方法 实现Runnable接口并实现run()方法 实现Callable接口并实现call()方法 1. 继承Thread类并重写run()方法 继承Thread类的方式是最简单也是最常用的开启新线…

    多线程 2023年5月17日
    00
  • Go并发:使用sync.WaitGroup实现协程同步方式

    下面详细讲解如何使用sync.WaitGroup实现协程同步的完整攻略。 什么是协程同步? 在使用协程进行并发编程时,我们常常需要等待所有协程都执行完毕后再进行某些操作,这时候我们就需要协程同步。协程同步指的是在并发编程中,协调多个协程的执行顺序,确保它们可以在特定的时间点同步。 WaitGroup的使用 WaitGroup是Go语言中提供的一种机制,它可以…

    多线程 2023年5月17日
    00
  • Python threading多线程编程实例

    Python threading是一个多线程编程模块,使用它可以让程序在多个线程中同时执行代码。在某些情况下,多线程可以提高程序的执行效率和性能。以下是Python threading多线程编程的完整攻略。 理解多线程编程 多线程编程是指在程序中同时运行多个线程,每个线程可以独立执行不同的代码。这个过程中,多线程共享代码的散列表、全局变量和堆栈等内存空间,但…

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