如何确保线程在分离之前已复制资源?

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

我需要使用

pthread_create
创建一个新线程,稍后它将分离。新线程需要复制一些内容,分离后这些内容将超出范围。下面是一个例子。我的问题是如何确保在分离之前将内容复制到新线程?

我必须在这里使用pthread来微调线程优先级。

#include <thread>
#include <iostream>
#include <pthread.h>
#include <chrono>

using namespace std::chrono_literals;

void new_thread() {
    int val = 65535;
    pthread_t pid;
    pthread_create(&pid, NULL, [](void* ptr)->void *{
        auto val_ptr = static_cast<int*>(ptr);
        auto val = *val_ptr;  // <-- copy from main thread
        std::cout<<"new thread: copied"<<std::endl;
        for (int i = 0; i<10; ++i) {
            std::cout<<"new thread: "<<"i:"<<i<<" val:"<<val<<std::endl;
            std::this_thread::sleep_for(10ms);
        }
        return nullptr;
    }, &val);
    std::cout<<"new thread created"<<std::endl;
    pthread_detach(pid);  // need to make sure val is copied before detach
    std::cout<<"new thread detached"<<std::endl;
}

int main() {
    new_thread();
    std::this_thread::sleep_for(1s);
}
c++ multithreading pthreads
1个回答
0
投票

在这里回答我自己的问题:

我认为我在问题中过于强调使用

pthread
,而这仍然可能是
std::thread
的问题。

根据建议,我尝试了以下 3 种方法:使用

pthread
、使用
std::thread
以及使用
std::thread
+ lambda capture,这使得将数据复制到新线程不再是问题。欢迎任何建议/更正。

#include <thread>
#include <pthread.h>
#include <iostream>
#include <chrono>
#include <mutex>
#include <condition_variable>

using namespace std::chrono_literals;

void new_pthread() {
    pthread_t pid;

    struct data_to_new_thread_t{
        int val = 11111;
        pthread_mutex_t mux = PTHREAD_MUTEX_INITIALIZER;
        pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
    } data;

    pthread_create(&pid, NULL, [](void* ptr)->void *{
        std::this_thread::sleep_for(10ms);  //  assuming the copy took a while
        auto val_ptr = static_cast<data_to_new_thread_t*>(ptr);
        auto val = val_ptr->val;  // <-- copy from main thread
        pthread_cond_signal(&val_ptr->cv);
        std::cout<<"new pthread: copied"<<std::endl;
        for (int i = 0; i<5; ++i) {
            std::cout<<"new pthread: "<<"i:"<<i<<" val:"<<val<<std::endl;
            std::this_thread::sleep_for(10ms);
        }
        return nullptr;
    }, &data);
    std::cout<<"new pthread created"<<std::endl;

    pthread_mutex_lock(&data.mux);
    pthread_cond_wait(&data.cv, &data.mux);
    pthread_mutex_unlock(&data.mux);
    std::cout<<"try to detach"<<std::endl; 
    pthread_detach(pid);  // need to make sure val is copied before detach
    std::cout<<"new pthread detached"<<std::endl;
    pthread_mutex_destroy(&data.mux);
    pthread_cond_destroy(&data.cv);
}

void new_std_thread() {
    std::mutex mux;
    std::condition_variable cv;
    bool is_copy_done = false;

    int val = 22222;
    auto t = std::thread([&](){
        std::this_thread::sleep_for(10ms); // assuming the copy took a while
        auto new_val = val;
        is_copy_done = true;
        cv.notify_all();
        std::cout<<"new thread: copied"<<std::endl;
        for (int i = 0; i<5; ++i) {
            std::cout<<"new thread: "<<"i:"<<i<<" val:"<<new_val<<std::endl;
            std::this_thread::sleep_for(10ms);
        }
    });
    std::cout<<"new thread created"<<std::endl;

    std::unique_lock<std::mutex> lock(mux);
    cv.wait(lock, [&is_copy_done]{return is_copy_done;});
    std::cout<<"try to detach"<<std::endl; 
    t.detach();
    std::cout<<"new thread detached"<<std::endl;
}


void new_std_thread_with_capture() {
    int val = 33333;
    auto t = std::thread([val](){  // capture by copy
        std::this_thread::sleep_for(10ms); // wait a while for detach
        for (int i = 0; i<5; ++i) {
            std::cout<<"new thread with capture: "<<"i:"<<i<<" val:"<<val<<std::endl;
            std::this_thread::sleep_for(10ms);
        }
    });
    std::cout<<"new thread created"<<std::endl;

    std::cout<<"try to detach"<<std::endl; 
    t.detach();
    std::cout<<"new thread detached"<<std::endl;
}

int main() {
    new_pthread();
    std::this_thread::sleep_for(1s);
    std::cout<<"=================="<<std::endl;
    new_std_thread();
    std::this_thread::sleep_for(1s);
    std::cout<<"=================="<<std::endl;
    new_std_thread_with_capture();
    std::this_thread::sleep_for(1s);
}
© www.soinside.com 2019 - 2024. All rights reserved.