簡體   English   中英

不使用條件暫停pthreads

[英]Suspend pthreads without using condition

我想暫停pthreads,但顯然,沒有像pthread_suspend這樣的函數。 我在某處讀到了使用互斥鎖和條件暫停pthreads並將其用於以下內容:

#include <pthread.h>

class PThread {
public:
pthread_t myPthread;
pthread_mutex_t m_SuspendMutex;
pthread_cond_t m_ResumeCond;

void start() {
pthread_create(&myPthread, NULL, threadRun, (void*)this );
}

Thread() { }

void suspendMe() {
pthread_cond_wait(&m_ResumeCond,&m_SuspendMutex);
}

void resume() {
pthread_cond_signal(&m_ResumeCond);
}
};

但我不明白為什么我們需要互斥和條件來暫停和恢復pthread。 是否可以在不使用條件的情況下暫停和恢復它?

您的代碼不正確 - pthread_cond_wait()要求在您調用互斥鎖時已鎖定互斥鎖:

void suspendMe()
{
    pthread_mutex_lock(&m_SuspendMutex);
    pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
    pthread_mutex_unlock(&m_SuspendMutex);
}

但是,這仍然是錯誤的。 一個線程可以從醒來pthread_cond_wait()任何名稱, 並不一定只有當它發出信號。 這意味着您需要將pthread_cond_wait()與某個共享狀態配對,該共享狀態對線程實際等待的條件進行編碼 - 在最簡單的情況下,您可以使用標志變量。 pthread_cond_signal()用於告訴線程它應該喚醒並重新檢查共享狀態。 將此應用於您的實現:

class PThread {
    public:

    pthread_t myPthread;
    bool suspended;
    pthread_mutex_t m_SuspendMutex;
    pthread_cond_t m_ResumeCond;

    void start() {
        suspended = false;
        pthread_create(&myPthread, NULL, threadRun, (void*)this );
    }

    Thread() { }

    void suspendMe() {
        pthread_mutex_lock(&m_SuspendMutex);
        suspended = true;
        do {
            pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
        } while (suspended);
        pthread_mutex_unlock(&m_SuspendMutex);
    }

    void resume() {
        /* The shared state 'suspended' must be updated with the mutex held. */
        pthread_mutex_lock(&m_SuspendMutex);
        suspended = false;
        pthread_cond_signal(&m_ResumeCond);
        pthread_mutex_unlock(&m_SuspendMutex);
    }
};

提供互斥鎖的原因是為了保護共享狀態並避免競爭條件 - pthread_cond_wait()函數在等待時實際執行原子解鎖和等待,這樣可以避免“錯過喚醒”。 例如,在該代碼時,互斥防止suspended更改為false的之間suspended = true; pthread_cond_wait()行。

如果一個線程沒有在某種條件下等待,你怎么能“發信號”它恢復。 它不能只是停止執行任何事情,然后再次神奇地重新開始,所以等待條件。

詳細說明,在pthreads中,恢復線程的方法實際上是使用條件變量。 沒有可用於以任何其他方式掛起/恢復線程的API。 等待pthread_cond_wait是便宜的,它會阻塞直到條件發出信號,而不是使用(多?)CPU。 您使用條件來通知線程喚醒,並且需要互斥鎖來保護對條件變量的訪問以及喚醒時線程中的代碼。

條件始終與互斥鎖相關聯。 通常,線程會休眠,因為它正在等待狀態的改變以指示它有工作要做; 你需要互斥鎖來保護對該狀態的訪問,以及發出變化信號的條件。

喚醒一個線程而不告訴它為什么你會喚醒它是一件有點奇怪的事情,所以沒有特別的方法去做; 唯一的方法是使用普通機制,但沒有共享狀態。

如果由於某種原因你想要從另一個線程暫停和恢復線程,而不是讓它工作,那么你可以使用pthread_kill向它發送SIGSTOPSIGCONT信號; 我從來沒有嘗試過這樣的事情,所以我不知道它是否得到支持。

看起來沒有任何Linux替代Windows API SuspendThread功能。 如果不在該線程過程中注入任何代碼,則無法暫停Linux線程。

互斥鎖用於確保獨占訪問,其中條件變量用於根據事件同步線程。

我們需要Mutexes來確保條件變量不會在無限等待中結束。 要記住的一件事是鎖定和解鎖的Mutex操作保證是原子的,但條件變量不一定是。 即,當條件變量wait等待一半時,線程可以被調度。

考慮以下情況,使用Mutex作為條件變量。

線程1


1)執行某些操作
2)等待條件變量
3)繼續操作

線程2


1)執行一些操作
2)發出條件變量的信號
3)繼續操作

在線程1中,步驟2不保證是原子的。 如果線程1在完成步驟1之前被調度程序推出RUNNING狀態。 現在線程2開始執行並發出條件變量的信號。 當線程1恢復執行時,它將完成剩余的低電平指令並開始等待。 線程1在無限等待中結束,因為條件變量的信號甚至在等待之前發生。

所以正確的使用方法是(我相信問題中提到的代碼沒有達到預期效果)

線程1: -


1)工作到必須發生某種情況的程度(例如“計數”必須達到指定值)
2)鎖定相關的互斥鎖
3)調用pthread_cond_wait()以對來自Thread1的信號執行阻塞等待。 (注意,對pthread_cond_wait()的調用會自動並原子地解鎖相關的互斥鎖變量,以便Thread2可以使用它
4)發出信號時,喚醒。 互斥鎖自動鎖定原子。
5)明確解鎖互斥鎖

線程2


1)做好工作
2)鎖定相關的互斥鎖
3)更改Thread1正在等待的全局變量的值。
4)檢查全局Thread1等待變量的值。 如果它滿足所需條件,則發出Thread1信號。
5)解鎖互斥鎖。 繼續

更重要的是 - 你最終想做什么? - 我懷疑答案不是'暫停一個帖子'。 可能是您的程序設計存在問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM