MST

星途 面试题库

面试题:C语言Linux异步I/O与多线程交互

假设你正在开发一个基于Linux C语言的多线程服务器,其中部分线程使用异步I/O进行数据读写。请阐述如何避免在异步I/O和多线程之间出现资源竞争问题,并给出一个简单的代码示例来展示关键的同步机制。
22.3万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

避免资源竞争的方法

  1. 互斥锁(Mutex):用于保护共享资源,在访问共享资源前加锁,访问结束后解锁,确保同一时间只有一个线程能访问该资源。
  2. 条件变量(Condition Variable):与互斥锁配合使用,线程可以等待某个条件满足后再继续执行,避免无效的循环等待。
  3. 读写锁(Read - Write Lock):如果共享资源主要是读操作,可使用读写锁,允许多个线程同时读,但写操作时需独占,以保证数据一致性。

代码示例

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

#define BUFFER_SIZE 1024

// 共享资源
char buffer[BUFFER_SIZE];
pthread_mutex_t mutex;
pthread_cond_t cond;

// 模拟异步I/O完成的标志
int io_completed = 0;

// 异步I/O控制块
struct aiocb my_aiocb;

// 线程函数,执行异步I/O
void* async_io_thread(void* arg) {
    // 初始化异步I/O控制块
    memset(&my_aiocb, 0, sizeof(struct aiocb));
    my_aiocb.aio_fildes = STDIN_FILENO;
    my_aiocb.aio_buf = buffer;
    my_aiocb.aio_nbytes = BUFFER_SIZE;
    my_aiocb.aio_offset = 0;

    // 发起异步读操作
    if (aio_read(&my_aiocb) == -1) {
        perror("aio_read");
        pthread_exit(NULL);
    }

    // 等待异步I/O完成
    while (aio_error(&my_aiocb) == EINPROGRESS);

    // 获取锁
    pthread_mutex_lock(&mutex);
    io_completed = 1;
    // 通知等待的线程
    pthread_cond_signal(&cond);
    // 释放锁
    pthread_mutex_unlock(&mutex);

    pthread_exit(NULL);
}

// 主线程,处理数据
int main() {
    pthread_t tid;

    // 初始化互斥锁和条件变量
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    // 创建线程执行异步I/O
    if (pthread_create(&tid, NULL, async_io_thread, NULL) != 0) {
        perror("pthread_create");
        return EXIT_FAILURE;
    }

    // 获取锁
    pthread_mutex_lock(&mutex);
    // 等待异步I/O完成
    while (!io_completed) {
        pthread_cond_wait(&cond, &mutex);
    }
    // 释放锁
    pthread_mutex_unlock(&mutex);

    // 处理数据
    printf("Data read from async I/O: %s\n", buffer);

    // 清理
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    pthread_join(tid, NULL);

    return EXIT_SUCCESS;
}

在上述代码中:

  1. 互斥锁mutex:用于保护io_completed这个共享资源,确保在修改和读取它时不会出现竞争。
  2. 条件变量cond:主线程通过pthread_cond_wait等待异步I/O完成的通知,避免了无效的循环等待,提高了效率。
  3. 异步I/O线程在完成I/O操作后,通过pthread_cond_signal通知主线程。