Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 添加作业期间,如果消除了1纳秒的延迟,std线程作业系统将中止_C++_Multithreading - Fatal编程技术网

C++ 添加作业期间,如果消除了1纳秒的延迟,std线程作业系统将中止

C++ 添加作业期间,如果消除了1纳秒的延迟,std线程作业系统将中止,c++,multithreading,C++,Multithreading,我已经包括了项目的全部来源,只有大约100行。 这是一个多线程作业系统,我正在为一个学校作业而工作,在为此挣扎了几天之后,主要是因为这对我来说都是非常新的(C++11和std线程) 我对thread、mutex和condition_变量类有基本的了解。但是,应用程序会抛出一个调试错误:R6010 abort()已被调用。当我在向池中添加单个作业的过程中删除1纳秒睡眠调用时。通过在访问和获取作业的过程中放置互斥锁,我希望解决这个错误,但这是徒劳的 #include "stdafx.h" #incl

我已经包括了项目的全部来源,只有大约100行。 这是一个多线程作业系统,我正在为一个学校作业而工作,在为此挣扎了几天之后,主要是因为这对我来说都是非常新的(C++11和std线程)

我对thread、mutex和condition_变量类有基本的了解。但是,应用程序会抛出一个调试错误:
R6010 abort()已被调用。
当我在向池中添加单个作业的过程中删除1纳秒睡眠调用时。通过在访问和获取作业的过程中放置互斥锁,我希望解决这个错误,但这是徒劳的

#include "stdafx.h"
#include <iostream>
#include <queue>
#include <future>
#include <thread>
#include <atomic>
using namespace std;

float CalcInvSqr(float x){
    return (x);
}

class ThreadPool{
public:
    ThreadPool::ThreadPool(int numThreads){
        for(int i=0;i<numThreads;i++){
            threads.push_back(thread(&ThreadPool::StartThread, this));
        }
    };

    ThreadPool::~ThreadPool(){
        CleanUp();
    }

    template<typename F>
    future<F> AddJob(std::packaged_task<F()>& job) {
        unique_lock<mutex> lock(poolMutex);
        this->jobList.push([&job]() {
            job();
        });

        this->cv.notify_one();
        lock.unlock();
        return job.get_future();
    }

    void StartThread(){
        while(true){

            unique_lock<mutex> uLock(poolMutex);
            cv.wait(uLock);

            if(stopped.load())
                return;

            std::function<void()> f;
            f = jobList.front();
            jobList.pop();

            uLock.unlock();
            f();
        }
    }

    void CleanUp(){
        stopped.store(true);
        {
            unique_lock<mutex> lock(poolMutex);
            cv.notify_all();
            lock.unlock();

            for(int i=0;i<threads.size();i++){
                if(threads[i].joinable())
                    threads[i].join();
            }

            cout<<jobList.size()<<endl;
        }
    }


private:
    mutable std::queue<std::function<void()>> jobList;
    atomic<bool> stopped;
    std::vector<std::thread> threads;
    std::mutex poolMutex;
    std::condition_variable cv;
};

#define JOBS 50

int main(){

    ThreadPool pool(4);

    std::vector<std::future<float>> results;
    for(int i=0;i<JOBS;i++){
        std::this_thread::sleep_for(std::chrono::nanoseconds(1));
        float num = (float)(rand()%RAND_MAX)/(float)RAND_MAX;
        std::packaged_task<float()> task([num](){
            return CalcInvSqr(num);
        });
        results.push_back(pool.AddJob<float>(task));
    }

    for(int i=0;i<JOBS;i++){
        cout<<"VALUE: "<<results[i].get()<<endl;
    }

    cout<<"Jobs Done ! "<<endl;
    system("PAUSE");
    return 0;
}
#包括“stdafx.h”
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
浮点数VSQR(浮点数x){
返回(x);
}
类线程池{
公众:
线程池::线程池(int numThreads){
对于(int i=0;ijobst.push([&job])(){
job();
});
此->cv.notify_one();
lock.unlock();
返回工作。获取未来();
}
void StartThread(){
while(true){
唯一锁定锁定(池互斥);
cv.等待(uLock);
if(stopped.load())
返回;
std::函数f;
f=作业列表。前();
jobList.pop();
uLock.unlock();
f();
}
}
空洞清理(){
停止。存储(true);
{
唯一锁(池互斥锁);
cv.通知所有人();
lock.unlock();

对于(int i=0;i让我们分析一下希望线程调用的函数对象会发生什么情况。一步一步:

  • main()
  • 任务通过引用传递给
    AddJob()
  • AddJob()
    中,任务通过对lambda函数的引用传递
  • 保存引用的lambda函数存储在
    ThreadPool
    对象中,供线程稍后进行计算
  • AddJob()
    返回一个未来,然后将其推送到
    results
    vector
  • 推送完成后,循环块结束,
    任务
    被销毁
  • 如果在将
    线程推送到
    线程池::作业列表
    和销毁
    任务
    对象之间的短时间内,线程没有处理
    任务
    中的函数,则保存在
    作业列表
    中的函数将保留对无效内存的引用,因为
    任务
    中的函数对象已销毁调用引用的-不再存在-函数的线程失败,导致软件中止

    由于
    std::packaged_task
    不可复制,您可能希望移动
    task
    的内容并将其存储在
    线程池
    对象中

    另外,仅供参考,额外的延迟对我的Linux机器没有帮助


    例子 我修改了两个方法,将
    打包的_任务
    s存储在
    线程池
    对象中。因为
    打包的_任务
    的内容是按值存储和移动的,只有在线程处理完后才会被销毁。请注意
    emplace
    std::move
    AddJob()
    中的使用

    模板
    未来添加作业(标准::打包的任务和作业){
    唯一锁(池互斥锁);
    auto future=job.get_future();
    这->作业列表.emplace(std::move(job));
    此->cv.notify_one();
    lock.unlock();
    回归未来;
    }
    void StartThread(){
    while(true){
    唯一锁定锁定(池互斥);
    cv.等待(uLock);
    if(stopped.load())
    返回;
    自动f=std::move(jobList.front());
    jobList.pop();
    uLock.unlock();
    f();
    }
    }
    可变std::队列作业列表;
    


    同样,如凯西在评论中提到的,你应该初始化<代码> thcCult::停止并考虑保护你的代码避免虚假唤醒。在我的系统中,<代码>停止< /COD>被评估为真,所以没有线程正在做他们的作业。< /P> < P>这里是修正的程序。 请注意,在通知条件变量之前,互斥锁已解锁。这一点很重要

    您会注意到,我在ThreadPool::Add中使用了一个共享的_ptr。这是因为代码是为c++11编写的。如果是c++14,我们可以取消共享的_ptr,只需将打包的_任务移动到lambda中就可以了

    #include <iostream>
    #include <queue>
    #include <future>
    #include <thread>
    #include <atomic>
    using namespace std;
    
    float CalcInvSqr(float x){
        return (x);
    }
    
    class ThreadPool{
    public:
        ThreadPool(int numThreads){
            for(int i=0;i<numThreads;i++){
                threads.push_back(thread(&ThreadPool::StartThread, this));
            }
        };
    
        ~ThreadPool(){
            CleanUp();
        }
    
        template<typename F>
        std::future<F> AddJob(std::packaged_task<F()> job)
        {
            auto job_ptr = make_shared<std::packaged_task<F()>>(move(job));
    
            unique_lock<mutex> lock(_job_mutex);
    
            jobList.push_back([job_ptr]() {
                job_ptr->operator()();
            });
            lock.unlock();
            _jobs_available.notify_one();
            return job_ptr->get_future();
        }
    
        void StartThread(){
            while (true) {
                unique_lock<mutex> job_lock(_job_mutex);
                _jobs_available.wait(job_lock, [this]() { return !stopped && !jobList.empty(); });
                if (stopped)
                    return;
                auto job = move(jobList.front());
                jobList.pop_front();
                job_lock.unlock();
                job();
            }
        }
    
        void CleanUp(){
            unique_lock<mutex> job_lock(_job_mutex);
            stopped = true;
            jobList.clear();
            job_lock.unlock();
            _jobs_available.notify_all();
    
            for (auto& thread : threads) {
                if (thread.joinable())
                    thread.join();
            }
        }
    
    
    private:
        std::mutex _job_mutex;
        std::condition_variable _jobs_available;
    
        std::deque<std::function<void()>> jobList;
        atomic<bool> stopped;
        std::vector<std::thread> threads;
    };
    
    #define JOBS 5000
    
    int main(){
    
        ThreadPool pool(40);
    
        std::vector<std::future<float>> results;
        for(int i=0;i<JOBS;i++){
            float num = (float)(rand()%RAND_MAX)/(float)RAND_MAX;
            std::packaged_task<float()> task([num](){
                return CalcInvSqr(num);
            });
            results.push_back(pool.AddJob<float>(move(task)));
        }
    
        for(int i=0;i<JOBS;i++){
            cout<<"VALUE: "<<results[i].get()<<endl;
        }
    
        cout<<"Jobs Done ! "<<endl;
        //    system("PAUSE");
        return 0;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    使用名称空间std;
    浮点数VSQR(浮点数x){
    返回(x);
    }
    类线程池{
    公众:
    线程池(int numThreads){
    对于(int i=0;ioperator());
    });
    lock.unlock();
    _作业可用。通知一个();
    return job_ptr->get_future();
    }
    void StartThread(){
    while(true){
    唯一锁定作业锁定(\u作业\u互斥体);
    _jobs_available.wait(job_lock,[this](){return!stopped&!jobList.empty();});
    如果(停止)
    返回;
    自动作业=移动(jobList.front());
    作业列表。pop_front();
    job_lock.unlock();
    job();
    }
    }
    空洞清理(){
    唯一锁定作业锁定(\u作业\u互斥体);
    停止=真;
    jobList.clear();
    job_lock.unlock();
    _作业可用。通知所有作业();
    用于(自动线程:线程(&T){
    if(thread.joinable())
    thread.join();
    }
    }
    私人:
    std::mutex\u job\u mutex;
    std::条件变量可用;
    std::德克工作清单;
    原子停止;
    向量线程;
    };
    #定义工作5000
    int main(){
    线程池(40);
    std::矢量结果;
    
    对于(int i=0;如果我可以在我的系统上很容易地复制它,+1是一个完整的可编译示例。不过,解决方案……在
    AddJob
    中,
    #include <iostream>
    #include <queue>
    #include <future>
    #include <thread>
    #include <atomic>
    using namespace std;
    
    float CalcInvSqr(float x){
        return (x);
    }
    
    class ThreadPool{
    public:
        ThreadPool(int numThreads){
            for(int i=0;i<numThreads;i++){
                threads.push_back(thread(&ThreadPool::StartThread, this));
            }
        };
    
        ~ThreadPool(){
            CleanUp();
        }
    
        template<typename F>
        std::future<F> AddJob(std::packaged_task<F()> job)
        {
            auto job_ptr = make_shared<std::packaged_task<F()>>(move(job));
    
            unique_lock<mutex> lock(_job_mutex);
    
            jobList.push_back([job_ptr]() {
                job_ptr->operator()();
            });
            lock.unlock();
            _jobs_available.notify_one();
            return job_ptr->get_future();
        }
    
        void StartThread(){
            while (true) {
                unique_lock<mutex> job_lock(_job_mutex);
                _jobs_available.wait(job_lock, [this]() { return !stopped && !jobList.empty(); });
                if (stopped)
                    return;
                auto job = move(jobList.front());
                jobList.pop_front();
                job_lock.unlock();
                job();
            }
        }
    
        void CleanUp(){
            unique_lock<mutex> job_lock(_job_mutex);
            stopped = true;
            jobList.clear();
            job_lock.unlock();
            _jobs_available.notify_all();
    
            for (auto& thread : threads) {
                if (thread.joinable())
                    thread.join();
            }
        }
    
    
    private:
        std::mutex _job_mutex;
        std::condition_variable _jobs_available;
    
        std::deque<std::function<void()>> jobList;
        atomic<bool> stopped;
        std::vector<std::thread> threads;
    };
    
    #define JOBS 5000
    
    int main(){
    
        ThreadPool pool(40);
    
        std::vector<std::future<float>> results;
        for(int i=0;i<JOBS;i++){
            float num = (float)(rand()%RAND_MAX)/(float)RAND_MAX;
            std::packaged_task<float()> task([num](){
                return CalcInvSqr(num);
            });
            results.push_back(pool.AddJob<float>(move(task)));
        }
    
        for(int i=0;i<JOBS;i++){
            cout<<"VALUE: "<<results[i].get()<<endl;
        }
    
        cout<<"Jobs Done ! "<<endl;
        //    system("PAUSE");
        return 0;
    }