![](/img/trans.png)
[英]C++ threads: How to stop one thread from executing while other is still running (Win32)
[英]C++, pthreads: how to stop a worker thread from multiple threads
我需要能夠阻止單個工作線程繼續從任意其他線程(包括但不限於主線程)中的任意點繼續執行。 去年,我編寫了我認為可以正常工作的代碼,但是在進行了一些線程死鎖之后,今天的調查表明,它似乎無法正常工作,尤其是在互斥鎖方面。
每次在主線程中調用輔助方法start_path_explorer()時,代碼都需要在工作線程中恰好運行一次特定方法path_explorer_t :: step()。 僅從主線程調用start_path_explorer()。
另一個方法stop_path_explorer()必須能夠在任何時間(除了運行path_explorer_t :: step()的線程之外)隨時被任何線程調用,並且除非確定path_explorer_t :: step()已完全釋放,否則它不得返回。完成。
此外,如果karte_t :: world-> is_terminate_threads()為true,則不得調用path_explorer_t :: step(),而必須在下一個機會終止線程。 該線程不得在其他情況下終止。
我為此編寫的代碼如下:
void* path_explorer_threaded(void* args) { karte_t* world = (karte_t*)args; path_explorer_t::allow_path_explorer_on_this_thread = true; karte_t::path_explorer_step_progress = 2; do { simthread_barrier_wait(&start_path_explorer_barrier); karte_t::path_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::path_explorer_step_progress = 2; pthread_mutex_unlock(&path_explorer_mutex); break; } path_explorer_t::step(); karte_t::path_explorer_step_progress = 1; pthread_cond_signal(&path_explorer_conditional_end); karte_t::path_explorer_step_progress = 2; pthread_mutex_unlock(&path_explorer_mutex); } while (!karte_t::world->is_terminating_threads()); karte_t::path_explorer_step_progress = -1; pthread_exit(NULL); return args; } void karte_t::stop_path_explorer() { #ifdef MULTI_THREAD_PATH_EXPLORER pthread_mutex_lock(&path_explorer_mutex); if (path_explorer_step_progress = 0) { pthread_cond_wait(&path_explorer_conditional_end, &path_explorer_mutex); } pthread_mutex_unlock(&path_explorer_mutex); #endif } void karte_t::start_path_explorer() { #ifdef MULTI_THREAD_PATH_EXPLORER if (path_explorer_step_progress == -1) { // The threaded path explorer has been terminated, so do not wait // or else we will get a thread deadlock. return; } pthread_mutex_lock(&path_explorer_mutex); if (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* world = (karte_t*)args; path_explorer_t::allow_path_explorer_on_this_thread = true; karte_t::path_explorer_step_progress = 2; int mutex_error = 0; do { simthread_barrier_wait(&start_path_explorer_barrier); karte_t::path_explorer_step_progress = 0; simthread_barrier_wait(&start_path_explorer_barrier); if (karte_t::world->is_terminating_threads()) { karte_t::path_explorer_step_progress = 2; break; } path_explorer_t::step(); mutex_error = pthread_mutex_lock(&path_explorer_mutex); karte_t::path_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::path_explorer_step_progress = 2; mutex_error = pthread_mutex_unlock(&path_explorer_mutex); } while (!karte_t::world->is_terminating_threads()); karte_t::path_explorer_step_progress = -1; pthread_exit(NULL); return args; } void karte_t::stop_path_explorer() { #ifdef MULTI_THREAD_PATH_EXPLORER int mutex_error = 0; while (path_explorer_step_progress == 0) { mutex_error = pthread_mutex_lock(&path_explorer_mutex); pthread_cond_wait(&path_explorer_conditional_end, &path_explorer_cond_mutex); if (&path_explorer_mutex) { mutex_error = pthread_mutex_unlock(&path_explorer_mutex); mutex_error = pthread_mutex_unlock(&path_explorer_cond_mutex); } } #endif } void karte_t::start_path_explorer() { #ifdef MULTI_THREAD_PATH_EXPLORER if (path_explorer_step_progress == -1) { // The threaded path explorer has been terminated, so do not wait // or else we will get a thread deadlock. return; } if (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 }
但是,我認為此代碼無法完全正常工作。 以此為基礎的軟件(一種開放源代碼的計算機游戲)被設計為可以使用鎖步網絡在Internet上以多玩家配置在互聯網上播放(這意味着服務器和客戶端必須從定義的起點完全確定地執行代碼,或者他們將不同步)。 使用此代碼時,客戶端最終將與服務器不同步,而客戶端將與原始代碼不同步(前提是服務器和客戶端運行的是相同的可執行文件:客戶端和服務器退出時遇到麻煩當可執行文件的編譯方式不同時(例如,GCC和Visual Studio,並且我懷疑未定義的行為可能是造成這種情況的罪魁禍首)。
如果有人可以確認我的新代碼是正確的還是存在任何明顯的缺陷,我將不勝感激。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.