gpt4 book ai didi

c - 在所有线程上读取相同的结构

转载 作者:太空宇宙 更新时间:2023-11-04 00:51:00 25 4
gpt4 key购买 nike

我希望所有线程都从同一个结构中读取。我过去是通过在从结构读取的循环中添加线程来做到这一点的,但这次我需要在 void“dowork”中打开结构,如我的示例所示。

我有以下代码:

struct word_list {
char word[20];
struct word_list * next;
};

struct word_list * first_word = NULL;
//other function which loads into struct is missing cause it's not relevant


//in main()
pthread_t thread_id[MAX_THREADS];
int max_thread = 10;
for(t = 0 ; t < max_thread; t++)
{
pthread_mutex_lock(&thrd_list);
arg_struct *args = calloc(1, sizeof(*args));
args->file = file;
args->t = t;
args->e = ex;
pthread_mutex_unlock(&thrd_list);
if(pthread_create(&thread_id[t],NULL,dowork,args) != 0)
{
t--;
fprintf(stderr,RED "\nError in creating thread\n" NONE);
}
}

for(t = 0 ; t < max_thread; t++)
if(pthread_join(thread_id[t],NULL) != 0)
{
fprintf(stderr,RED "\nError in joining thread\n" NONE);
}




void *dowork(void *arguments)
{
struct word_list * curr_word = first_word;
char myword[20];
while( curr_word != NULL )
{
pthread_mutex_lock(&thrd_list);
strncpy(myword,curr_word->word,sizeof(myword) - 1);
pthread_mutex_unlock(&thrd_list);

//some irrelevant code is missing

pthread_mutex_lock(&thrd_list);
curr_word = curr_word->next;
pthread_mutex_unlock(&thrd_list);
}

}

如何在所有线程中读取同一结构中的不同元素?

最佳答案

如果我现在理解了您的要求(我想我终于理解了),您需要将您的单词列表视为一个工作队列。为此需要一种通知机制,允许将项目“插入”队列以通知“拉出者”新数据可用。 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 进行一些研究,尤其是互斥锁和条件变量控制及其交互。希望对您有所帮助。

关于c - 在所有线程上读取相同的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18789894/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com