怎样才能使rand()即使被mutex保护,也能为线程返回相同的值?

问题描述 投票:1回答:1

我希望为在freeRTOS环境中运行的3个线程生成随机值。我知道rand()不是线程安全的,所以我使用了一个mutex来保护它。此外,我只调用了一次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;
    }
}

没有做到这一点(如果有更好的实现建议,请不要犹豫),而且线程在得到值后会把它放到一个struct中,不知道这是否有帮助。每个线程在自己的结构体中)。

更新2

这里是结构,以及如何保存值。

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


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

UPDATE 3

下面是第一个和第二个线程结构实现的例子。

#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,运行这么说,但他们是相同的在同一运行。下面左边的图片是我的小程序打印在右边的简单随机打印。enter image description here

更新5

另一个奇怪的事情是,每次我运行这段代码时,我得到的数字序列都是一样的,就好像stand从来没有被调用过一样(即使它被调用了),即使我用time(NULL)+clock()作为srand()的种子,每次都应该是不同的。也许它可以帮助...

c multithreading random task freertos
1个回答
0
投票

所以,不知道完全是为什么,但是,只有当srand()被调用3次(每次任务运行时,但在无限循环之外,所以它只运行一次,在xTaskCreate创建任务时提供的函数中),而不是在main()中只调用一次时,它才会工作。如果它在main()函数中只被调用一次,那么随机值就如同从未调用过srand()函数一样。我猜测(只是猜测,还没有任何证据),这是因为每个任务都有自己的栈。

谢谢大家协助排除故障......

© www.soinside.com 2019 - 2024. All rights reserved.