You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言多线程同时访问变量问题咨询(传感器执行器场景)

解决C语言多线程传感器-执行器应用的同步问题

嘿,我懂你现在面临的麻烦——两个线程同时操作共享变量sensor_values,这种读写竞争绝对会搞出乱子:要么读出来的是半更新的数据,要么程序直接出现莫名其妙的行为,完全不符合预期。别慌,咱们用线程同步机制就能搞定这个问题,最常用的就是互斥锁,下面给你一步步拆解。

首先,先明确核心问题:C语言里的普通变量没有线程安全保障,当一个线程在读取变量的同时,另一个线程写入,这属于未定义行为,系统完全不保证结果的正确性。

方案一:用互斥锁(pthread_mutex_t)实现排他访问

互斥锁的作用很简单:同一时间只允许一个线程持有锁,持有锁的线程才能访问共享资源,其他线程必须等待锁释放。这就彻底避免了读写冲突。

给你修改后的完整示例代码:

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

// 共享传感器数据变量
int sensor_values;
// 定义互斥锁,保护共享变量
pthread_mutex_t sensor_mutex;

// 模拟从硬件读取传感器数据的函数
int some_sensor_read_function() {
    // 这里替换成你的实际硬件读取逻辑,比如从GPIO或者串口读数据
    static int val = 0;
    return val++ % 100; // 模拟数据变化
}

// 读传感器线程:负责读取并解析传感器数据
void* read_sensor(void* arg) {
    while (1) {
        // 加锁:确保读取时没有线程在写
        pthread_mutex_lock(&sensor_mutex);
        int current_val = sensor_values;
        printf("[读线程] 读取到传感器值:%d\n", current_val);
        // 解锁:释放锁让其他线程可以访问
        pthread_mutex_unlock(&sensor_mutex);

        // 模拟传感器读取间隔,实际根据硬件调整
        sleep(1);
    }
    return NULL;
}

// 执行器控制线程:根据传感器值控制执行器启停
void* control_actuator(void* arg) {
    while (1) {
        // 加锁:确保修改共享变量时没有线程在读
        pthread_mutex_lock(&sensor_mutex);
        // 更新传感器值(实际是从硬件读取后赋值)
        sensor_values = some_sensor_read_function();
        // 根据值判断执行器动作
        if (sensor_values > 50) {
            printf("[控制线程] 传感器值超过阈值,启动执行器\n");
            // 这里添加你的执行器启动逻辑
        } else {
            printf("[控制线程] 传感器值低于阈值,停止执行器\n");
            // 这里添加你的执行器停止逻辑
        }
        // 解锁
        pthread_mutex_unlock(&sensor_mutex);

        // 模拟控制间隔,实际根据需求调整
        sleep(2);
    }
    return NULL;
}

int main() {
    pthread_t read_thread, control_thread;

    // 初始化互斥锁,一定要做这一步!
    if (pthread_mutex_init(&sensor_mutex, NULL) != 0) {
        perror("互斥锁初始化失败");
        return 1;
    }

    // 创建两个线程
    if (pthread_create(&read_thread, NULL, read_sensor, NULL) != 0) {
        perror("创建读传感器线程失败");
        return 1;
    }
    if (pthread_create(&control_thread, NULL, control_actuator, NULL) != 0) {
        perror("创建执行器控制线程失败");
        return 1;
    }

    // 等待线程结束(这里因为是死循环,实际可能需要信号来终止)
    pthread_join(read_thread, NULL);
    pthread_join(control_thread, NULL);

    // 销毁互斥锁,释放资源
    pthread_mutex_destroy(&sensor_mutex);

    return 0;
}

关键注意事项

  • 锁的配对:加锁后必须解锁,哪怕函数中途出错返回,否则会导致死锁(其他线程永远拿不到锁)。如果你的代码里有分支提前返回,可以用goto统一处理解锁,或者在每个返回前手动解锁。
  • 锁的粒度:不要在持有锁的时候执行耗时操作(比如长时间的IO、sleep),否则会让另一个线程一直等待,拖慢程序响应速度。
  • 初始化与销毁:互斥锁必须用pthread_mutex_init初始化,用完后用pthread_mutex_destroy销毁,避免资源泄漏。

备选方案:读写锁(pthread_rwlock_t)

如果你的应用里读操作远多于写操作,读写锁会比互斥锁更高效——它允许多个读线程同时持有读锁,只有写线程需要独占锁。示例用法如下:

#include <pthread.h>

pthread_rwlock_t sensor_rwlock;

// 读线程中使用读锁
void* read_sensor(void* arg) {
    while(1) {
        pthread_rwlock_rdlock(&sensor_rwlock);
        int val = sensor_values;
        pthread_rwlock_unlock(&sensor_rwlock);
        // ...其他逻辑
    }
}

// 写线程中使用写锁
void* control_actuator(void* arg) {
    while(1) {
        pthread_rwlock_wrlock(&sensor_rwlock);
        sensor_values = new_val;
        pthread_rwlock_unlock(&sensor_rwlock);
        // ...其他逻辑
    }
}

读写锁的初始化和销毁用pthread_rwlock_init和pthread_rwlock_destroy,和互斥锁类似。

这样处理后,你的两个线程就能安全地共享sensor_values变量,不会再出现读写冲突的问题啦。

内容的提问来源于stack exchange,提问作者Mário Marques

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:39:33