MST

星途 面试题库

面试题:C语言fread和fwrite在复杂场景下的异常处理

在一个多线程环境中,多个线程同时使用`fread`和`fwrite`对同一个文件进行读写操作,可能会出现哪些问题?如何通过合理的机制(如文件锁、线程同步等)来避免这些问题?请详细阐述并给出代码示例说明如何在代码层面实现这些机制。
19.2万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

可能出现的问题

  1. 数据竞争:多个线程同时读写文件,可能导致数据不一致。例如,一个线程正在写入数据时,另一个线程开始读取,可能读到部分写入的数据,造成数据错误。
  2. 文件指针混乱:每个线程独立操作文件指针,可能使文件指针的位置错乱,导致读写位置不正确。

避免问题的机制

  1. 文件锁
    • 建议使用fcntl函数:在POSIX系统中,fcntl函数可以用于设置文件锁。通过设置不同类型的锁(如读锁、写锁),可以控制多个线程对文件的访问。
    • 示例代码
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>
#include <unistd.h>

#define FILE_NAME "test.txt"

// 写线程函数
void* write_thread(void* arg) {
    int fd = open(FILE_NAME, O_WRONLY | O_CREAT, 0666);
    struct flock lock;
    lock.l_type = F_WRLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;
    // 获取写锁
    fcntl(fd, F_SETLKW, &lock);
    const char* data = "Hello, from write thread!";
    write(fd, data, strlen(data));
    // 释放写锁
    lock.l_type = F_UNLCK;
    fcntl(fd, F_SETLK, &lock);
    close(fd);
    return NULL;
}

// 读线程函数
void* read_thread(void* arg) {
    int fd = open(FILE_NAME, O_RDONLY);
    struct flock lock;
    lock.l_type = F_RDLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;
    // 获取读锁
    fcntl(fd, F_SETLKW, &lock);
    char buffer[100];
    ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);
    buffer[bytes_read] = '\0';
    printf("Read data: %s\n", buffer);
    // 释放读锁
    lock.l_type = F_UNLCK;
    fcntl(fd, F_SETLK, &lock);
    close(fd);
    return NULL;
}

int main() {
    pthread_t write_tid, read_tid;
    // 创建写线程
    pthread_create(&write_tid, NULL, write_thread, NULL);
    // 创建读线程
    pthread_create(&read_tid, NULL, read_thread, NULL);
    // 等待写线程结束
    pthread_join(write_tid, NULL);
    // 等待读线程结束
    pthread_join(read_tid, NULL);
    return 0;
}
  1. 线程同步
    • 使用互斥锁:在C语言中,可以使用POSIX线程库的互斥锁(pthread_mutex_t)。在进行文件读写操作前,先获取互斥锁,操作完成后释放互斥锁,这样可以保证同一时间只有一个线程能访问文件。
    • 示例代码
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>

#define FILE_NAME "test.txt"
pthread_mutex_t mutex;

// 写线程函数
void* write_thread(void* arg) {
    FILE* file = fopen(FILE_NAME, "w");
    pthread_mutex_lock(&mutex);
    const char* data = "Hello, from write thread!";
    fwrite(data, strlen(data), 1, file);
    fclose(file);
    pthread_mutex_unlock(&mutex);
    return NULL;
}

// 读线程函数
void* read_thread(void* arg) {
    FILE* file = fopen(FILE_NAME, "r");
    pthread_mutex_lock(&mutex);
    char buffer[100];
    fread(buffer, 1, sizeof(buffer) - 1, file);
    buffer[feof(file)? strlen(buffer) : sizeof(buffer) - 1] = '\0';
    printf("Read data: %s\n", buffer);
    fclose(file);
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
    pthread_t write_tid, read_tid;
    pthread_mutex_init(&mutex, NULL);
    // 创建写线程
    pthread_create(&write_tid, NULL, write_thread, NULL);
    // 创建读线程
    pthread_create(&read_tid, NULL, read_thread, NULL);
    // 等待写线程结束
    pthread_join(write_tid, NULL);
    // 等待读线程结束
    pthread_join(read_tid, NULL);
    pthread_mutex_destroy(&mutex);
    return 0;
}