我的情況是,每個給定的時間間隔(比如說 1 秒)我都需要生成一個遵循預先確定的一組操作的執行緒。然后在完成之后,我需要以某種方式清理與該執行緒關聯的資源。但是我不確定如何在生成新執行緒的同時做到這一點,因為 pthread_join 是阻塞的,所以我不能在等待其他執行緒完成的同時繼續生成新執行緒。
我見過建議做這樣的事情的典型方法是:
int i;
pthread_t threads[NUM_THREADS];
for (i = 0; i < NUM_THREADS; i) {
pthread_create(&threads[i], NULL, mythread, NULL);
}
for (i = 0; i < NUM_THREADS; i) {
pthread_join(threads[i], NULL);
}
但是,我不想在開始時生成預定數量的執行緒并讓它們運行。我想一次生成一個執行緒,然后繼續生成(這沒關系,因為執行緒達到飽和點,如果它們超過 100 個,它們只會在第一步結束)。我想到的一種解決方案是讓 pthread_joins 在他們自己的執行緒中運行,但是我不確定如何告訴它要加入哪些執行緒。這些執行緒在它們內部具有隨機的睡眠時間,因此沒有指定它們應該完成的順序。我想到的程式應該如何運行是這樣的:
- 執行緒 [1] 創建/運行
- 執行緒 [2] 創建/運行
- 執行緒 [3] 創建/運行
- 執行緒 [2] 完成 -> 加入/釋放記憶體
- new Thread[2] created/running(由于 2 完成,現在創建一個新執行緒 2)
因此,例如,您運行的執行緒永遠不會超過 5 個,但每次運行完成時,您都會創建一個新執行緒。執行緒不一定需要在一個陣列中,我只是認為這樣會更容易管理。我已經考慮了好幾個小時了,想不出解決辦法。我只是以完全錯誤的方式解決問題,并且有更簡單的方法嗎?
uj5u.com熱心網友回復:
pthread_join是加入執行緒的函式,而不是等待它們。是的,呼叫者會等到執行緒從啟動函式回傳,但這只是一個副作用。
等待執行緒是通過條件變數 ( pthread_cond_wait ) 或障礙 ( pthread_barrier_wait ) 完成的。
另一種方法是引入一個全域串列,其中將存盤已完成的執行緒(在退出執行緒之前,將執行緒添加到該串列中)。并且每個間隔(我從您的主要功能中假設),從串列中處理并加入所有執行緒。我認為我不必提及該串列必須受互斥體保護。
例如
struct thread_data {
struct thread_data *next; //single linked list instead of array
pthread_t id; //thread id
void *priv_data; //some data needed for other functionality
bool in_use; //test flag to indicate
//if the specific data/thread is in use/running
};
//mutex to protect the global garbage data
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
//global list for garbage collection, protected via 'lock'
struct thread_data *garbage = NULL;
//thread starting function
void* thread_func(void *arg)
{
//1. cast 'arg' to 'struct thread_data'
struct thread_data *data = (struct thread_data*) arg;
//2. do your other stuff
//3. before returning/exiting
pthread_mutex_lock(&lock);
//add data to garbage
data->next = garbage;
garbage = data;
pthread_mutex_unlock(&lock);
return NULL;
}
int main()
{
#define MAX_THREADS 5 //some arbitrary number
struct thread_data data[MAX_THREADS]; //main data storage
while (true) {
//1. your sleep/wait routine
//2. on wake up, collect garbage first
pthread_mutex_lock(&lock);
for (; garbage ; garbage = garbage->next) {
//destroy garbage->priv_data, if not already done somewhere else
pthread_join(garbage->id); //clear thread resources
garbage->in_use = false; //data no longer in use, free to reuse
}
pthread_mutex_unlock(&lock);
//3. iterate over data storage and if a reusable data is found,
//create the thread and pass the specific data
//as argument to the thread starting function
for (int i=0; i < MAX_THREADS; i) {
if (!data[i].in_use) {
data[i].in_use = true;
//data[i].priv_data = ...
pthread_create(&data[i].id, NULL, thread_func, &data[i]);
break; //we only want one thread at a time, right?
}
}
}
return 0;
}
uj5u.com熱心網友回復:
pthread_tryjoin_np當您要創建一個新執行緒時,您可以呼叫現有執行緒。(這是 POSIX 的 GNU 擴展。)您可以創建一個已完成執行緒的串列,并在您即將創建一個新執行緒時加入它們并清空串列。一個易于實作的堆疊可以用作串列。
您可以分離執行緒,以便自動清理它們。您將需要一種機制來等待執行緒在存在主程式之前完成,但這可以通過 cond var 輕松完成。
uj5u.com熱心網友回復:
主執行緒:
- 將計數信號量初始化為 5
- 信號量下降
- 啟動執行緒
- 環回
作業執行緒:
- 作業
- 清理
- 信號量向上
- 死
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/523279.html
標籤:C多线程线程正则表达式
上一篇:Julia:向量的并行函式
下一篇:異步運行多個行程
