在 C 中的线程之间切换
Switch between threads in C
我正在尝试编写执行此操作的代码:
输入 1:
2
123
abc
输出:
1a2b3c
第一行是下面的行数和我必须使用的线程数(最多 10 个)。
随机字符的行可能有不同的大小。
输入 2:
5
abcdef
123456789
xyz
ghi
j
输出 2:
a1xgjb2yhc3zid4e5f6789
我正在尝试使用互斥锁,但到目前为止我无法解决它。
任何帮助表示赞赏。
这是我的代码:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int n_strings;
char chars[10][100];
char output[1000];
pthread_t thread[10];
int count = 0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INICIALIZER;
void* mix_it_up(void* arg)
{
char* a = (char*) arg;
for (int i = 0; i < strlen(a); i++)
{
pthread_mutex_lock(&mutex);
output[count++] = a[i];
pthread_mutex_unlock(&mutex);
}
}
int main(void)
{
scanf("%d", &n_strings);
for (int i = 0; i < n_strings; i++)
{
scanf("%s", chars[i]);
}
for (int i = 0; i < n_strings; i++)
{
pthread_create(&thread[i], NULL, mix_it_up, (void*) chars[i]);
}
for (int i = 0; i < n_strings; ++i)
{
pthread_join(thread[i], NULL);
}
pthread_mutex_destroy(&mutex);
printf("%s\n", output);
return(0);
}
感谢任何帮助。谢谢
除了你的全局互斥体,还有一个全局条件变量:
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
还有一个附加变量来指示轮到哪个线程:
static int running_thread = 0;
每个线程都需要知道它有哪个序列号。不是从 chars 传递元素,而是传递 index
for (int i = 0; i < n_strings; i++)
{
pthread_create(&thread[i], NULL, mix_it_up, (void*)i);
}
那么你的线程需要在一个循环中等待获取访问权限。然后它通过更新 running_thread
并向所有线程发出信号以从它们的等待循环中唤醒以查看是否轮到它们来传递控制权。
void* mix_it_up(void* arg)
{
int threadid = (int)arg;
char* a = chars[threadid];
for (int i = 0; i < strlen(a); i++)
{
pthread_mutex_lock(&mutex);
// wait for our turn
while (running_thread != threadid)
{
pthread_cond_wait(&cond, &mutex); // releases locks and waits for notify
// mutex lock is implicitly re-acquired when cond_wait returns
}
output[count++] = a[i];
// indicate which thread runs next
running_thread = (running_thread + 1) % n_strings;
// notify other threads to wakeup from pthread_cond_wait
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
这种方法的一个缺点是每次 pthread_cond_broadcast
调用时总会有 N-2 个线程被不必要地唤醒。这对于 ~10 个线程来说完全没问题。但是如果你有数百个线程,那么每个线程唤醒的开销就会大很多,再次获取互斥锁,运行,检查是否(running_thread != threadid)
,然后返回等待。
一种更复杂的方法是让所有线程共享 N pthread_cond_t
而不是仅 1 个。他们的方式是,每个线程都可以被显式唤醒,而不是通知所有线程唤醒。如果您有超过 10 个线程,这将是一个不错的方法。请记住,您仍然需要在每次(虚假)唤醒时检查 (running_thread != threadid)
。换句话说,一个信号量。
我正在尝试编写执行此操作的代码:
输入 1:
2
123
abc
输出:
1a2b3c
第一行是下面的行数和我必须使用的线程数(最多 10 个)。 随机字符的行可能有不同的大小。
输入 2:
5
abcdef
123456789
xyz
ghi
j
输出 2:
a1xgjb2yhc3zid4e5f6789
我正在尝试使用互斥锁,但到目前为止我无法解决它。 任何帮助表示赞赏。
这是我的代码:
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int n_strings;
char chars[10][100];
char output[1000];
pthread_t thread[10];
int count = 0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INICIALIZER;
void* mix_it_up(void* arg)
{
char* a = (char*) arg;
for (int i = 0; i < strlen(a); i++)
{
pthread_mutex_lock(&mutex);
output[count++] = a[i];
pthread_mutex_unlock(&mutex);
}
}
int main(void)
{
scanf("%d", &n_strings);
for (int i = 0; i < n_strings; i++)
{
scanf("%s", chars[i]);
}
for (int i = 0; i < n_strings; i++)
{
pthread_create(&thread[i], NULL, mix_it_up, (void*) chars[i]);
}
for (int i = 0; i < n_strings; ++i)
{
pthread_join(thread[i], NULL);
}
pthread_mutex_destroy(&mutex);
printf("%s\n", output);
return(0);
}
感谢任何帮助。谢谢
除了你的全局互斥体,还有一个全局条件变量:
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
还有一个附加变量来指示轮到哪个线程:
static int running_thread = 0;
每个线程都需要知道它有哪个序列号。不是从 chars 传递元素,而是传递 index
for (int i = 0; i < n_strings; i++)
{
pthread_create(&thread[i], NULL, mix_it_up, (void*)i);
}
那么你的线程需要在一个循环中等待获取访问权限。然后它通过更新 running_thread
并向所有线程发出信号以从它们的等待循环中唤醒以查看是否轮到它们来传递控制权。
void* mix_it_up(void* arg)
{
int threadid = (int)arg;
char* a = chars[threadid];
for (int i = 0; i < strlen(a); i++)
{
pthread_mutex_lock(&mutex);
// wait for our turn
while (running_thread != threadid)
{
pthread_cond_wait(&cond, &mutex); // releases locks and waits for notify
// mutex lock is implicitly re-acquired when cond_wait returns
}
output[count++] = a[i];
// indicate which thread runs next
running_thread = (running_thread + 1) % n_strings;
// notify other threads to wakeup from pthread_cond_wait
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
这种方法的一个缺点是每次 pthread_cond_broadcast
调用时总会有 N-2 个线程被不必要地唤醒。这对于 ~10 个线程来说完全没问题。但是如果你有数百个线程,那么每个线程唤醒的开销就会大很多,再次获取互斥锁,运行,检查是否(running_thread != threadid)
,然后返回等待。
一种更复杂的方法是让所有线程共享 N pthread_cond_t
而不是仅 1 个。他们的方式是,每个线程都可以被显式唤醒,而不是通知所有线程唤醒。如果您有超过 10 个线程,这将是一个不错的方法。请记住,您仍然需要在每次(虚假)唤醒时检查 (running_thread != threadid)
。换句话说,一个信号量。