我需要使用
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);
}
在这里回答我自己的问题:
我认为我在问题中过于强调使用
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);
}