记录一个多线程用来收发数据的数据结构,以及一点踩坑日记

正文

我有两个线程,一个线程专门用来收数据,一个线程专门用来发数据,因此我有两个list结构的链表,一个用来收数据,一个用来发数据,暂称为recvlistsendlist;为了确保线程安全,我使用了两个锁。

代码逻辑是这样的:

recvlist在一般情况下含有多个元素,而sendlist正常情况下是空的。两个线程同时工作,每次接收线程在接收数据的时候,就弹出recvlist头部的元素,填充之后,就将该元素放入sendlist中。而发送线程检测到sendlist不为空时,就将sendlist中的元素弹出来,发送出去。循环往复

逻辑是没毛病的,下面看实际实现过程:

首先是对两个list存取数据的操作:

void buf_put(std::list<type* >&list, type* element, pthread_mutex& mutex)
{
    // 加锁
    pthread_mutex_lock(mutex);
    // 将元素压入list尾部:如果是recvlist,尾部数据已经不需要再使用了
    list.push_back(element);
    // 解锁
    pthread_mutex_unlock(mutex);
}

type* buf_take(std::list<type* >&list, pthread_mutex& mutex)
{
    // 加锁
    pthread_mutex_lock(mutex);
    
    // 获取当前元素并弹出
    type* element = list.front();
    list.pop_front();

    // 解锁
    pthread_mutex_unlock(mutex);

    // 返回,外部接收
    return element;
}

错误描述

根据排查,发现在进行buf_put()操作的时候,一切正常,sendlist中每次压入的也都是正常的数据,但对sendlist进行buf_put操作的时候,大部分时候取到的数据都是错误的,只有偶尔取到的数据是正常的。集中体现在element->len的值为 -1

错误原因

原因已经找到,错误的地方并不在于对两个list存取数据的操作...原因在于如果使用指针作为函数的参数进行传递,如:

void functionA()
{
    demo_struct demo1;
    demo_struct* ptr1 = &demo1;
    functionB(ptr1);
}
void functionB(demo_struct* ptr)
{
    // TODO:
}

在函数functionB()中,ptr作为一个指针被传递过来,在上面例子中,指针ptr指向结构体demo1,通过对ptr进行操作,可以修改demo1中数据的值,可以修改指针ptr指向的地址的值,但是,在函数functionB()中,无法修改指针ptr本身的值,因为它本身是个指针,因此指针的值指的就是指针本身的地址。

如果想在一个函数中修改另一个函数中定义的指针的值,那么在函数间传递的参数应该是这个指针的指针,而非这个指针本身。示例如下:

#include <stdio.h>

typedef struct demo_struct{
    char buf[10];
    int  len;

} demo_struct;

void functionB(demo_struct** ptr)
{
    fprintf(stdout, "access into functionB()\n");
    *ptr = NULL;
    fprintf(stdout, "ptr = NULL\n");
}

void functionA()
{
    demo_struct demo1;
    demo_struct* demo_ptr1 = &demo1;
    if (NULL != demo_ptr1)
        fprintf(stdout, "test start!\n");

    functionB(&demo_ptr1);

    if (demo_ptr1 == NULL)
        fprintf(stdout, "test successfully\n");
}

int main()
{
    functionA();
    return 0;
}


标题:记录一个多线程用来收发数据的数据结构,以及一点踩坑日记
作者:staymeloo7
联系方式:staycoolsun@gmail.com

    评论
    0 评论
avatar

取消