首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程返回意外的结果- c++

线程返回意外的结果- c++
EN

Stack Overflow用户
提问于 2022-04-18 13:42:22
回答 1查看 63关注 0票数 0

我正在学习有关家庭作业的线程,并尝试在我编写的一个简单程序上实现线程。没有线程程序的完美工作,但当我线程两个随机数生成器函数,它返回不正确的结果。结果似乎总是'42‘的两个数字生成器,不知道为什么会是这样。

另外,对于上下文,我只是从线程开始,所以我理解这个程序不需要多线程。我这么做只是为了学习。

谢谢你的帮助!

代码语言:javascript
复制
// struct for vector to use
struct readings {
    std::string name;
    int data;
};

// random generator for heat value - stores in vector of struct
void gen_heat(std::vector<readings>& storage) {
    readings h = {"Heat", rand() % 100 + 1};
    storage.insert(storage.begin(), h);
}

// random generator for light value - stores in vector of struct
void gen_light(std::vector<readings>& storage) {
    readings l = {"Light", rand() % 100 + 1};
    storage.insert(storage.begin(), l);
}

int main() {
    // vector of readings struct
    std::vector<readings> storage;

    srand(time(NULL));

    // initialising threads of random generators
    std::thread H(gen_heat, std::ref(storage));
    std::thread L(gen_light, std::ref(storage));

    // waiting for both to finish
    H.join();
    L.join();

    // print values in vec of struct
    for (const auto& e : storage) {
        std::cout << "Type: " << e.name << std::endl
                  << "Numbers:  " << e.data << std::endl;
    }

    // send to another function
    smartsensor(storage);

    return 0;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-18 14:29:51

由于您有几个线程访问一个相互的资源,在本例中是读取向量,而且其中一些线程正在修改它,因此您需要使对该资源的访问成为独占的。同步访问的方法有很多种;其中一种方法非常简单,而且不涉及互斥对象的使用,其中之一是二进制信号量 (自C++20)。你基本上:

  1. 通过获取信号量拥有对资源的访问权,
  2. 利用资源,然后,
  3. 释放信号量,以便其他人可以访问资源。

如果线程A试图在其他线程B使用该资源时获取信号量,则线程A将被阻塞,直到资源被释放。

注意,信号量被初始化为1,指示资源是空闲的。一旦一个线程获得了信号量,计数就会下降到0,直到计数返回到1 (在release之后会发生什么),其他线程才能获得它。

[演示]

代码语言:javascript
复制
#include <cstdlib>  // rand
#include <iostream>  // cout
#include <semaphore>
#include <string>
#include <thread>
#include <vector>

std::binary_semaphore readings_sem{1};

// struct for vector to use
struct readings {
    std::string name;
    int data;
};

// random generator for heat value - stores in vector of struct
void gen_heat(std::vector<readings>& storage) {
    for (auto i{0}; i < 5; ++i) {
        readings_sem.acquire();
        readings h = {"Heat", rand() % 100 + 1};
        storage.insert(storage.begin(), h);
        readings_sem.release();
    }
}

// random generator for light value - stores in vector of struct
void gen_light(std::vector<readings>& storage) {
    for (auto i{0}; i < 5; ++i) {
        readings_sem.acquire();
        readings l = {"Light", rand() % 100 + 1};
        storage.insert(storage.begin(), l);
        readings_sem.release();
    }
}

int main() {
    // vector of readings struct
    std::vector<readings> storage;

    srand(time(NULL));

    // initialising threads of random generators
    std::thread H(gen_heat, std::ref(storage));
    std::thread L(gen_light, std::ref(storage));

    // waiting for both to finish
    H.join();
    L.join();

    // print values in vec of struct
    for (const auto& e : storage) {
        std::cout << "Type: " << e.name << std::endl
            << "Numbers:  " << e.data << std::endl;
    }
}

// Outputs (something like):
//
//   Type: Heat
//   Numbers:  5
//   Type: Light
//   Numbers:  83
//   Type: Light
//   Numbers:  40
//   ...

本·沃格特评论的最新进展

资源的获取和释放可以使用RAII (资源获取是初始化)来封装,这种机制已经由语言提供。例如:

  • 两个线程仍然试图获取一个互斥对象来访问读取资源的向量。
  • 但他们只是通过创建一个lock guard来获得它。
  • 一旦锁保护超出范围并被摧毁,互斥体就会被释放。

[演示]

代码语言:javascript
复制
#include <mutex>  // lock_guard

std::mutex mtx{};

// random generator for heat value - stores in vector of struct
void gen_heat(std::vector<readings>& storage) {
    for (auto i{0}; i < 5; ++i) {
        std::lock_guard<std::mutex> lg{ mtx };
        readings h = {"Heat", rand() % 100 + 1};
        storage.insert(storage.begin(), h);
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71912594

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档