什么会使 rand() return 对线程具有相同的值,即使它受互斥锁保护?

What would make rand() return the same value for threads even if it is protected by a mutex?

我希望在 freeRTOS 环境中为 3 个线程 运行ning 生成随机值。知道 rand() 不是线程安全的,我使用互斥锁来保护它。此外,我只调用了一次 srand() 。尝试解决此问题时应该考虑什么?

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "FreeRTOS.h"
#include "semphr.h"

#include "sensorDriver.h"

SemaphoreHandle_t semaphoreMutexDriver; 
uint16_t sensorValue; 

void sensorDriver_initialize()
{
    srand(time(NULL));
    semaphoreMutexDriver = xSemaphoreCreateMutex();
}

void getValue()
{
    if (xSemaphoreTake(semaphoreMutexDriver, portMAX_DELAY))
    {
        sensorValue = (uint16_t)(rand() % 50);
        xSemaphoreGive(semaphoreMutexDriver);
    }
}

uint16_t sensorDriver_getValue()
{
    getValue();

    return sensorValue;
}

可以根据要求添加更多代码。

更新 1

尝试将 sensorValue 设为函数的局部值,例如:

uint16_t firstSensorDriver_getValue()
{
    if (xSemaphoreTake(semaphoreMutexDriver, portMAX_DELAY))
    {
        uint16_t sensorValue = (uint16_t)(rand() % 50);
        xSemaphoreGive(semaphoreMutexDriver);

        return sensorValue;
    }
}

没成功(如果有更好的建议,请不要犹豫),线程在获取值后将其放入结构中,不确定是否有帮助。 (每个线程都有自己的结构)。

更新 2

这是结构以及值的保存方式:

struct firstSensor
{
     uint16_t firstSensorValue;
     EventGroupHandle_t meassureEventGroup;
     EventGroupHandle_t dataReadyEventGroup;
};


void firstSensor_fetchSensorValue(FirstSensor self)
{
     self->firstSensorValue = sensorDriver_getValue();
}

更新 3

这是第一个和第二个 thread/struct 实现的示例

#ifndef FIRSTSENSOR_H
#define FIRSTSENSOR_H

typedef struct firstSensor* FirstSensor; 

FirstSensor firstSensor_create(UBaseType_t taskPriority, EventGroupHandle_t 
eventGroupMeassure, EventGroupHandle_t eventGroupDataReady);
uint16_t firstSensor_getSensorValue(FirstSensor self);
void firstSensor_destroySensor(FirstSensor self);

#endif

和类似的第二个线程头文件和源文件

#ifndef SECONDSENSOR_H
#define SECONDSENSOR_H

typedef struct secondSensor* SecondSensor; 

SecondSensor secondSensor_create(UBaseType_t taskPriority, EventGroupHandle_t             
eventGroupMeassure, EventGroupHandle_t eventGroupDataReady);
uint16_t secondSensor_getSensorValue(SecondSensor self);
void secondSensor_destroySensor(SecondSensor self);

#endif

并实施

struct secondSensor
{
     uint16_t secondSensorValue;
     EventGroupHandle_t meassureEventGroup;
     EventGroupHandle_t dataReadyEventGroup;
};

void secondSensor_fetchSensorValue(SecondSensor self)
{
    self->secondSensorValue = firstSensorDriver_getValue();
}

void secondSensor_task(void* instance)
{
    EventBits_t eventBitsMeasure;
    SecondSensor self = (SecondSensor*)instance;

    for (;;)
    {
        eventBitsMeasure = xEventGroupWaitBits(self->meassureEventGroup, BIT_SECOND_SENSOR, pdTRUE, pdTRUE, portMAX_DELAY);

        if ((eventBitsMeasure & BIT_SECOND_SENSOR) == BIT_SECOND_SENSOR)
        {
            secondSensor_fetchSensorValue(self);
            xEventGroupSetBits(self->dataReadyEventGroup, BIT_SECOND_SENSOR);
        }
    }
}

更新 4 好吧,从技术上讲,它们对于每个 emm 都是随机的,运行 可以这么说,但它们在同一个 运行 中是相同的。下面左边的图片是我的小程序在右边简单随机打印的内容。

更新 5

另一个奇怪的事情是,每次我 运行 代码我得到相同的数字序列,就好像 stand 从未被调用(即使它是),即使我用时间播种 srand()( NULL) + clock() 每次都应该不同。也许它可以帮助...

所以,不完全确定为什么,但是,它只有在 srand() 被调用 3 次时才有效(每次任务运行,但在无限循环之外,因此它只运行一次,在 xTaskCreate 的函数中在创建任务时提供)而不是在 main() 中只提供一次。如果它在主函数中只被调用一次,那么随机值就好像 srand() 函数从未被调用过一样。我想(只是假设,还没有任何证据)这是因为每个任务都有自己的堆栈。

感谢大家协助解决问题...