周老师,请问一下多线程卡死和互斥锁的问题

#include <pthread.h>
#include <string.h>
#include <unistd.h>  // for usleep
#include "serial_main.h"
#include "lvgl/lvgl.h"
#include "serial_thread.h"

#if 1
pthread_t thread_id;  // 线程ID
pthread_t update_thread_id;  // 线程ID
pthread_mutex_t mutex;  // 互斥锁,用于保护全局数据访问
extern pthread_mutex_t mutex_1;  // 互斥锁,用于保护全局数据访问

//char received_data[MAX_DATA_LENGTH];  // 全局变量,存储接收到的数据
extern lv_obj_t *textarea;  // 声明一个外部变量, LVGL文本框对象指针
extern lv_obj_t * dropdown123;
char * new_data = NULL;  // 用于存储新选项的指针
char * data = NULL;

#if 1
// 线程函数,用于接收串口数据并更新LVGL文本框
void *thread_function(void *arg) {
    while (1) {
        //serial_recv();  // 调用串口接收函数
        //data = get_received_data();
        pthread_mutex_lock(&mutex);  // 加锁,保护全局数据访问
        if (data != NULL && strlen(data) > 0) {
            //new_data = strdup(data);  // 分配内存并复制数据
            lv_textarea_add_text(textarea, data);  // 更新LVGL文本框内容
            memset(data, 0, sizeof(data)); //用于将一块内存区域的内容设置为指定的值
            //new_data = data;
        }
        pthread_mutex_unlock(&mutex);  // 解锁
        usleep(1000);  // 添加适当的延迟以防止CPU占用过高
    }
    return NULL; 
}
#endif

#if 1
// 线程函数,用于将接收到的数据设置为下拉列表的选项
void * update_dropdown_thread(void *arg) { 
    //char options[] = "ABC\n123\nA2C\0";  // 模拟生成选项文本
    int i=0;                                                       
    while (1) {
        i++;
        pthread_mutex_lock(&mutex_1);  // 加锁,保护全局数据访问
        char *options[100] = {0};
        //sprintf(options, "ABC\n123\n%d\0", i);
        sprintf(options, "%s\n%d\0", data, i);
        free(new_data);  // 使用完毕后释放内存

        new_data = strdup(options);  // 复制选项文本
        LV_LOG_USER("update_dropdown_thread: Generating new options.");
        
        /*if (dropdown123 == NULL)
            LV_LOG_USER("下拉列表为空");
        else
            LV_LOG_USER("下拉列表不为空");*/

        if (dropdown123 != NULL && new_data != NULL) {
            lv_dropdown_clear_options(dropdown123);// 在更新下拉列表之前先清除旧选项
            lv_dropdown_set_options_static(dropdown123, new_data);  // 将接收到的数据设置为选项
            //new_data = NULL;  // 清空新选项指针
            LV_LOG_USER("update_dropdown_thread: 下拉列表更新成功");
        }
        //free(new_data);  // 使用完毕后释放内存
        pthread_mutex_unlock(&mutex_1);  // 解锁
        usleep(50*1000);  // 添加适当的延迟以防止CPU占用过高
    }
    return NULL;
}
#endif

// 初始化函数,用于创建线程和初始化其他必要资源
void initialize_serial_thread() {
    pthread_mutex_init(&mutex, NULL);  // 初始化互斥锁

    #if 1
    // 创建线程
    if (pthread_create(&thread_id, NULL, thread_function, NULL) != 0)  /*pthread_create用于创建一个新的线程, 函数返回一个整数值,如果成功创建线程,则返回0;如果失败,则返回一个非零值*/
    {
        perror("Failed to create thread");
        // 处理线程创建失败的情况
        // 可以选择退出程序或者采取其他错误处理措施
    }
    #endif

    #if 1
    if (pthread_create(&update_thread_id, NULL, update_dropdown_thread, NULL) != 0)  /*pthread_create用于创建一个新的线程, 函数返回一个整数值,如果成功创建线程,则返回0;如果失败,则返回一个非零值*/
    {
        perror("Failed to create thread");
        // 处理线程创建失败的情况
        // 可以选择退出程序或者采取其他错误处理措施
    }
    #endif
}
#endif

之前更新下拉列表文本的线程会出现卡死的情况,我把线程分开分别排查,现在解决这个问题,只开任何一个线程屏幕都不会出现卡死的情况,现在是两个线程都打开,烧录到触摸屏上,在串口接收数据后下拉列表文本并没有获取到串口发送的数据,并且屏幕还卡死了,这是接收串口数据线程代码哪里出现了问题,另外第二个线程需要将串口的数据用来更新下拉列表的选项,他们的互斥锁是否需要相同

pthread_mutex_t mutex_1;
int main(int argc, char **argv)
{
  (void)argc;
  (void)argv; 


  lv_init();

  hal_init();

  // 初始化互斥锁
  pthread_mutex_init(&mutex_1, NULL);
  
  create_layout(); 
  /* 初始化并创建串口接收线程 */
  initialize_serial_thread();
 
  while (1)
  {
    pthread_mutex_lock(&mutex_1);  // 加锁,保护全局数据访问
    lv_timer_handler();
    pthread_mutex_unlock(&mutex_1);  // 解锁
    usleep(5 * 1000); //5ms
  }

  return 0;
}
```这是mian.c文件中添加了更新下拉列表数据相同的互斥锁

看你的代码data指针变量的使用是有问题的,没看到分配,在update_dropdown_thread线程中使用前也没有对其进行检查;另外一个问题是,thread_function线程应该与LVGL所在的线程保持互斥关系,现在的 锁 mutex 是没有什么意义的

周老师,这个data指针变量是获取串口的数据地址,因为模拟时是无法查看硬件,这里我是先屏蔽掉了serial_recv(); 和data = get_received_data();你说的检查是判断指针变量是否为空吗,另外线程锁互斥意思是不用加锁吗

lvgl执行一次lv_timer_handler不一定能一次性久刷新完界面,这里建议如果你的ui处理不复杂就把lvgl相关处理都放在和lv_timer_handler同一个任务中

大佬,放在同一个任务中,意思是给两个线程加上相同的互斥锁吗