在函数中传递向量元素[关闭]

Posted

技术标签:

【中文标题】在函数中传递向量元素[关闭]【英文标题】:passing vector elements in a function [closed] 【发布时间】:2020-04-16 15:58:33 【问题描述】:

我是多线程新手,所以任何建议都会非常有用!我正在根据以下要求实现一个多线程程序:

用户输入整数列表作为向量。每个向量元素 N 代表一个细胞。 向量元素被传递给线程函数,从中计算特定时间的总单元格 计算单元的寿命(0.1 + N % 8 秒)。在其半生时,它们会繁殖出许多 (( N – N % 8 ) / 8 ) 个子细胞。 子细胞的寿命与它们的父细胞相同,但在它们的生命结束时会在没有繁殖的情况下死亡。 在创建第一个创世单元线程之前启动单元监视器。监测器会每秒打印出现有活细胞的数量,从而监测有多少活细胞。 主函数等待用户输入。给定向量输入,它将启动 监控线程,然后启动创世单元线程。

【问题讨论】:

return number; - 无人看管的评估;这本身就是一个问题。您会发现 std::lock_guard 在这里很有帮助。 您是否设法在没有线程的情况下完成这项工作?作为新用户,也请带上tour阅读How to Ask。 【参考方案1】:

问题中的代码给了我一些关于如何执行复制的不确定性,但我做了以下假设:

((N - N % 8) / 8) 是指每个父代产生多少个子cell,N,当它达到一半的生命周期时,这不是什么有问题的代码暗示 从创建之时开始,子细胞的生存时间与其父细胞相同 - 因此它们的寿命比父细胞长,而不是同时死亡,这又不是相关代码的作用

我用来完成概述的模拟的方案是有一个线程来控制time 变量,可以是主线程,也可以是专门为此目的创建的线程。该线程将根据需要增加时间,但将等待所有线程检查它们的单元是否已死亡或需要在增量之间重现并执行必要的操作。下面的示例演示了这种方法。

我发现当使用std::atomic 变量来存储活细胞数量、模拟时间、需要检查的线程数等时,这会更容易,也可能更清晰。使用原子变量时,为任何增量或减量执行必要的内存隔离,而不需要 std::mutex 或其他显式同步。此外,最好为细胞实现class,这样它们就可以存储自己的生命周期,如果它们还活着,无论是孩子还是父母,是否有孩子等等。

示例

#include <iostream>
#include <thread>
#include <atomic>
#include <vector>
#include <mutex>

class Cell 
public:
    Cell(int x, bool child = false) 
        lifetime = (0.1 + x % 8);
        n = x;
        is_child = child;
        alive = true;
        has_children = false;
    
    int lifetime;
    int n;
    bool is_child;
    bool has_children;
    bool alive;
;

std::mutex mtx;    // This will be used to synchronize threads.push_back()
                   // when creating children cells
std::vector<Cell> cells;
std::vector<std::thread> threads;

std::atomic<int> t;      // The simulation time
std::atomic<int> living; // The number of living cells
std::atomic<int> check;  // This will be used to ensure every thread goes through the 
                         // necessary checks every time step
void thread_function(Cell cell) 
    int prev = t;
    while (living > 0) 
        while (prev == t) if (living == 0) return;
        prev = (int)t;
        if (!cell.has_children && !cell.is_child && t > cell.lifetime / 2.0) 
            cell.has_children = true;
            // Create children and send them to new threads
            for (int ii = 0; ii < ((cell.n - cell.n % 8) / 8); ii ++) 
                living ++;
                Cell c(ii, true);               // Create a new cell which will die 
                c.lifetime = cell.lifetime + t; // lifetime seconds from now
                mtx.lock();
                threads.push_back(std::thread(thread_function, c));
                mtx.unlock();
            
        
        if (cell.alive && t >= cell.lifetime) 
            cell.alive = false;
            living --;
        
        check --;
    


int main(int argn, char** argv) 
    living = argn - 1;
    if (argn > 1) 
        for (int ii = 1; ii < argn; ii ++) 
            cells.push_back(Cell(atoi(argv[ii])));
            threads.push_back(std::thread(thread_function, cells[ii-1]));
        
    
    t = 0;

    while (living > 0) 
        std::cout << "Total Cells: "+std::to_string(living)+" [ "+std::to_string(t)+
            " s ]\n" << std::flush;
        check = threads.size();
        t ++;
        while (check > 0) 
            if (living == 0) break;
        
    
    std::cout << "Total Cells: "+std::to_string(living)+" [ "+std::to_string(t)+
        " s ]\n" << std::flush;

    for (int ii = 0; ii < threads.size(); ii ++) 
        threads[ii].join();
    

./cells 1 2 3 4 5 6 7
Total Cells: 7 [ 0 s ]
Total Cells: 6 [ 1 s ]
Total Cells: 5 [ 2 s ]
Total Cells: 4 [ 3 s ]
Total Cells: 3 [ 4 s ]
Total Cells: 2 [ 5 s ]
Total Cells: 1 [ 6 s ]
Total Cells: 0 [ 7 s ]

./cells 21 12 6 7 1 17 25
Total Cells: 7 [ 0 s ]
Total Cells: 9 [ 1 s ]
Total Cells: 4 [ 2 s ]
Total Cells: 7 [ 3 s ]
Total Cells: 6 [ 4 s ]
Total Cells: 5 [ 5 s ]
Total Cells: 4 [ 6 s ]
Total Cells: 2 [ 7 s ]
Total Cells: 0 [ 8 s ]

您可以通过包围checktliving 的每个增量和减量使用互斥锁来获得相同的结果。


注意 像我这样使用全局变量并不是一个好习惯,我这样做只是为了简化多线程的演示,实际上最好将它们包装在namespace 中,将整个模拟重构为class,或类似的东西。

【讨论】:

以上是关于在函数中传递向量元素[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何通过将向量元素传递给函数来更改它们

传递给函数后向量的大小发生变化

升序的向量元素[关闭]

传递给函数的向量没有被修改

对向量元素进行排序[关闭]

std :: sort不会移动向量的元素[关闭]