什么会使 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() 函数从未被调用过一样。我想(只是假设,还没有任何证据)这是因为每个任务都有自己的堆栈。
感谢大家协助解决问题...
我希望在 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() 函数从未被调用过一样。我想(只是假设,还没有任何证据)这是因为每个任务都有自己的堆栈。
感谢大家协助解决问题...