C++,pthreads:如何从多个线程停止工作线程
C++, pthreads: how to stop a worker thread from multiple threads
我需要能够阻止单个工作线程继续从任意其他线程中的任意点执行,包括但不限于主线程。我去年制作了我认为是工作的代码,但今天在一些线程死锁之后的调查表明它似乎无法正常工作,尤其是在互斥锁方面。
每次在主start_path_explorer线程中调用帮助程序方法 start_path_explorer() 时,代码都需要在工作线程中运行一次特定方法 path_explorer_t::step(
)。 另一个方法 stop_path_explorer() 必须能够随时由任何线程调用(运行 path_explorer_t::step()的线程除外),并且在确定 path_explorer_t::step() 完全完成之前不得返回。
此外,如果 karte_t::world->is_terminating_threads() 为 true,则不得调用 path_explorer_t::step(),而必须在下次有机会时终止线程。线程不得在其他情况下终止。
我为此编写的代码如下:
void* path_explorer_threaded(void* args) { karte_t* 世界 = (karte_t*)参数; path_explorer_t::allow_path_explorer_on_this_thread = 真; karte_t::p ath_explorer_step_progress = 2; 做 { simthread_barrier_wait(&start_path_explorer_barrier); karte_t::p ath_explorer_step_progress = 0; simthread_barrier_wait(&start_path_explorer_barrier); pthread_mutex_lock(&path_explorer_mutex); if (karte_t::world->is_terminating_threads()) { karte_t::p ath_explorer_step_progress = 2; pthread_mutex_unlock(&path_explorer_mutex); 破; } path_explorer_t::step(); karte_t::p ath_explorer_step_progress = 1; pthread_cond_signal(&path_explorer_conditional_end); karte_t::p ath_explorer_step_progress = 2; pthread_mutex_unlock(&path_explorer_mutex); } while (!karte_t::world->is_terminating_threads()); karte_t::p ath_explorer_step_progress = -1; pthread_exit(空); 返回参数; } 无效 karte_t::stop_path_explorer() { #ifdef MULTI_THREAD_PATH_EXPLORER pthread_mutex_lock(&path_explorer_mutex); 如果 (path_explorer_step_progress = 0) { pthread_cond_wait(&path_explorer_conditional_end,&path_explorer_mutex); } pthread_mutex_unlock(&path_explorer_mutex); #endif } 无效 karte_t::start_path_explorer() { #ifdef MULTI_THREAD_PATH_EXPLORER 如果 (path_explorer_step_progress == -1) { 线程路径资源管理器已终止,因此不要等待 否则我们将出现线程死锁。 返回; } pthread_mutex_lock(&path_explorer_mutex); 如果 (path_explorer_step_progress> 0) { simthread_barrier_wait(&start_path_explorer_barrier); } if(path_explorer_step_progress> -1) { simthread_barrier_wait(&start_path_explorer_barrier); } pthread_mutex_unlock(&path_explorer_mutex); #endif }
但是,我发现,由于我不理解的原因,stop_path_explorer() 中的互斥锁无法正常工作,并且它不会阻止互斥锁线在path_explorer_threaded中传递,结果是调用 stop_path_explorer() 的线程可能在cond_wait处等待,而工作线程本身可能在"do"下方的顶部屏障处等待。它似乎还能够产生互斥锁可以解锁两次的条件,这会导致未定义的行为,除非我将其设置为递归。
我只需要将互斥属性设置为递归并在 stop_path_explorer() 中的条件语句中添加额外的解锁,还是需要更基本的重新设计?如果是后者,有人对如何去做有任何建议吗?
提前感谢您的任何帮助。
在进一步调查之后,我认为我对自己的问题有一个潜在的答案。
我误解了 pthread_cond_wait() 如何与互斥锁结合使用 - 文档说它锁定,而不是解锁传递给它的互斥锁。
这意味着互斥锁从同一线程被双重锁定,这产生了未定义的行为,并且可能会导致我看到的一些奇怪的问题。
现在,我已使用第二个互斥锁重写了代码,如下所示(代码示例中未显示新定义):
void* path_explorer_threaded(void* args) { karte_t* 世界 = (karte_t*)参数; path_explorer_t::allow_path_explorer_on_this_thread = 真; karte_t::p ath_explorer_step_progress = 2; int mutex_error = 0; 做 { simthread_barrier_wait(&start_path_explorer_barrier); karte_t::p ath_explorer_step_progress = 0; simthread_barrier_wait(&start_path_explorer_barrier); if (karte_t::world->is_terminating_threads()) { karte_t::p ath_explorer_step_progress = 2; 破; } path_explorer_t::step(); mutex_error = pthread_mutex_lock(&path_explorer_mutex); karte_t::p ath_explorer_step_progress = 1; mutex_error = pthread_mutex_unlock(&path_explorer_mutex); pthread_cond_signal(&path_explorer_conditional_end); mutex_error = pthread_mutex_lock(&path_explorer_mutex); karte_t::p ath_explorer_step_progress = 2; mutex_error = pthread_mutex_unlock(&path_explorer_mutex); } while (!karte_t::world->is_terminating_threads()); karte_t::p ath_explorer_step_progress = -1; pthread_exit(空); 返回参数; } 无效 karte_t::stop_path_explorer() { #ifdef MULTI_THREAD_PATH_EXPLORER int mutex_error = 0; 而 (path_explorer_step_progress == 0) { mutex_error = pthread_mutex_lock(&path_explorer_mutex); pthread_cond_wait(&path_explorer_conditional_end,&path_explorer_cond_mutex); 如果 (&path_explorer_mutex) { mutex_error = pthread_mutex_unlock(&path_explorer_mutex); mutex_error = pthread_mutex_unlock(&path_explorer_cond_mutex); } } #endif } 无效 karte_t::start_path_explorer() { #ifdef MULTI_THREAD_PATH_EXPLORER 如果 (path_explorer_step_progress == -1) { 线程路径资源管理器已终止,因此不要等待 否则我们将出现线程死锁。 返回; } 如果 (path_explorer_step_progress> 0) { simthread_barrier_wait(&start_path_explorer_barrier); } if(path_explorer_step_progress> -1) { simthread_barrier_wait(&start_path_explorer_barrier); } #endif }
但是,我不相信这段代码完全正常工作。从中获取该软件的软件,一个开源计算机游戏,旨在使用锁步网络在多玩家配置中通过互联网播放(这意味着服务器和客户端必须准确地从定义的起点准确执行代码,否则它们将不同步)。使用此代码时,客户端最终将与服务器不同步,而它们不会与原始代码不同步(前提是服务器和客户端运行相同的可执行文件:当可执行文件以不同的方式编译时,我遇到了客户端和服务器不同步的问题,例如 GCC 和 Visual Studio, 我怀疑未定义的行为可能是那里的罪魁祸首)。
如果有人可以确认我的新代码是否正确或有任何明显的缺陷,我将不胜感激。
- C++ 线程创建/删除与线程停止/恢复
- 从线程池工作线程使用 GetQueuedCompletionStatus 的奇怪行为
- C++,pthreads:如何从多个线程停止工作线程
- 如何从另一个线程停止 std::cin 再读取输入?
- Qt 停止来自 GUI 线程的工作线程循环
- 如何使用pthreads使多线程正常工作,而不是使用C++在类中提升
- 如何处理任务,同时剩余的线程完成工作
- 有没有一种可靠的方法可以在C++中强制线程停止?(尤其是独立的)
- C++ std::线程池的线程停止条件
- 如何使 CDT/Eclipse 与 C++11 线程一起工作
- 如何从其他线程停止ReadDirectoryChangesW
- 无法让 modf() 在多线程中工作
- Visual c++只有一个线程在工作(OpenMP)
- OpenMP线程多于工作对性能的影响是什么?
- 代码步进如何与线程一起工作
- c++ 98:线程停止
- 使用boost::asio定时器进行线程安全工作
- 我正在学习c++服务器编程,但线程不工作
- 睡眠命令不能在子线程中工作
- Qt - 同步线程不起作用 - 线程停止但实际上不会停止,有时在不应该停止的时候停止