如果我现在了解您的要求(我想我终于了解了),您需要将您的单词列表视为工作队列。要做到这一点,需要一种通知机制,该机制允许将项目“推送”到队列中,以通知“拉取者”新数据可用。这样的系统确实存在于 pthread 中:条件变量、互斥体和它们为控制流管理的谓词的结合。
这是如何使用它的一个例子。我已尝试为您记录每个步骤中发生的情况,希望您能理解。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
// defined the number of threads in our queue and the number
// of test items for this demonstration.
#define MAX_THREADS 16
#define MAX_ITEMS 128*1024
typedef struct word_list
{
char word[20];
struct word_list * next;
} word_list;
// predicate values for the word list
struct word_list * first_word = NULL; // current word.
int word_shutdown = 0; // shutdown state
// used for protecting our list.
pthread_mutex_t wq_mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t wq_cv = PTHREAD_COND_INITIALIZER;
// worker proc
void *dowork(void*);
int main()
{
pthread_t thread_id[MAX_THREADS];
int i=0;
// start thread pool
for(i=0; i < MAX_THREADS; ++i)
pthread_create(thread_id+i, NULL, dowork, NULL);
// add MAX_ITEMS more entries, we need to latch since the
// work threads are actively processing the queue as we go.
for (i=0;i<MAX_ITEMS;++i)
{
word_list *node = malloc(sizeof(*node));
sprintf(node->word, "Word-%d", i);
// latch before updating the queue head.
pthread_mutex_lock(&wq_mtx);
node->next = first_word;
first_word = node;
// no longer need the latch. unlock and inform any
// potential waiter.
pthread_mutex_unlock(&wq_mtx);
pthread_cond_signal(&wq_cv);
}
// wait for the condition that the queue is empty
pthread_mutex_lock(&wq_mtx);
while (first_word != NULL)
pthread_cond_wait(&wq_cv, &wq_mtx);
pthread_mutex_unlock(&wq_mtx);
// queue is empty, but threads are all still there waiting. So
// do it again, just to proves the pool is still intact.
for (i=0;i<MAX_ITEMS;++i)
{
word_list *node = malloc(sizeof(*node));
sprintf(node->word, "Word-%d", i);
// latch before updating the queue head.
pthread_mutex_lock(&wq_mtx);
node->next = first_word;
first_word = node;
// no longer need the latch. unlock and inform any
// potential waiter.
pthread_mutex_unlock(&wq_mtx);
pthread_cond_signal(&wq_cv);
}
// again wait for the condition that the queue is empty
pthread_mutex_lock(&wq_mtx);
while (first_word != NULL)
pthread_cond_wait(&wq_cv, &wq_mtx);
// queue is empty, and we're not adding anything else. latch
// the mutex, set the shutdown flag, and tell all the threads.
// they need to terminate.
word_shutdown = 1;
pthread_mutex_unlock(&wq_mtx);
pthread_cond_broadcast(&wq_cv);
for (i=0;i<MAX_THREADS; ++i)
pthread_join(thread_id[i], NULL);
return EXIT_SUCCESS;
}
// the work crew will start by locking the mutex, then entering the
// work loop, looking for entries or a shutdown state
void *dowork(void *arguments)
{
int n_processed = 0;
while (1)
{
pthread_mutex_lock(&wq_mtx);
while (first_word == NULL && word_shutdown == 0)
pthread_cond_wait(&wq_cv, &wq_mtx);
// we own the mutex, and thus current access to the predicate
// values it protects.
if (first_word != NULL)
{
// pull the item off the queue. once we do that we own the
// item, so we can unlatch and let another waiter know there
// may be more data on the queue.
word_list *p = first_word;
first_word = p->next;
if (p->next)
pthread_cond_signal(&wq_cv);
pthread_mutex_unlock(&wq_mtx);
//
// TODO: process item here.
//
++n_processed;
free(p);
}
else if (word_shutdown != 0)
break;
}
// we still own the mutex. report on how many items we received, then
// one more signal to let someone (anyone, actually) know we're done.
pthread_t self = pthread_self();
printf("%p : processed %d items.\n",self, n_processed);
pthread_mutex_unlock(&wq_mtx);
pthread_cond_signal(&wq_cv);
return NULL;
}
示例输出:MAX_THREADS = 4(您的输出会有所不同)
0x100387000 : processed 64909 items.
0x100304000 : processed 64966 items.
0x1000b5000 : processed 64275 items.
0x100281000 : processed 67994 items.
样本输出:MAX_THREADS = 8
0x100304000 : processed 31595 items.
0x1000b5000 : processed 33663 items.
0x100593000 : processed 34298 items.
0x10040a000 : processed 32304 items.
0x10048d000 : processed 32406 items.
0x100387000 : processed 31878 items.
0x100281000 : processed 32317 items.
0x100510000 : processed 33683 items.
样本输出:MAX_THREADS = 16
0x10079f000 : processed 17239 items.
0x101081000 : processed 16530 items.
0x101104000 : processed 16662 items.
0x100699000 : processed 16562 items.
0x10040a000 : processed 16672 items.
0x100593000 : processed 15158 items.
0x10120a000 : processed 17365 items.
0x101187000 : processed 14184 items.
0x100387000 : processed 16332 items.
0x100616000 : processed 16497 items.
0x100281000 : processed 16632 items.
0x100304000 : processed 16222 items.
0x100510000 : processed 17188 items.
0x10048d000 : processed 15367 items.
0x1000b5000 : processed 16912 items.
0x10071c000 : processed 16622 items.
正因为我们可以,启用完整的全局优化
样本输出:MAX_THREADS = 32,MAX_ITEMS = 4194304
0x109c58000 : processed 260000 items.
0x109634000 : processed 263433 items.
0x10973a000 : processed 262125 items.
0x10921c000 : processed 261201 items.
0x108d81000 : processed 262325 items.
0x109a4c000 : processed 262318 items.
0x108f8d000 : processed 263107 items.
0x109010000 : processed 261382 items.
0x109946000 : processed 262299 items.
0x109199000 : processed 261930 items.
0x10929f000 : processed 263506 items.
0x109093000 : processed 262362 items.
0x108e87000 : processed 262069 items.
0x108e04000 : processed 261890 items.
0x109acf000 : processed 261875 items.
0x1097bd000 : processed 262040 items.
0x109840000 : processed 261686 items.
0x1093a5000 : processed 262547 items.
0x109b52000 : processed 261980 items.
0x109428000 : processed 264259 items.
0x108f0a000 : processed 261620 items.
0x1095b1000 : processed 263062 items.
0x1094ab000 : processed 261811 items.
0x1099c9000 : processed 262709 items.
0x109116000 : processed 261628 items.
0x109bd5000 : processed 260905 items.
0x10952e000 : processed 262741 items.
0x1098c3000 : processed 260608 items.
0x109322000 : processed 261970 items.
0x1000b8000 : processed 262061 items.
0x100781000 : processed 262669 items.
0x1096b7000 : processed 262490 items.
嗯。我没有使用volatile
任何这些。一定是时候买彩票了。
无论如何,我建议对 pthread 进行一些研究,尤其是互斥体和条件变量控制及其交互。我希望这能够帮到你。