我无法找到解决问题的正确方法。
如果我在一个进程中有多个线程。我想在同一个进程中运行其他线程时只让一个线程进入睡眠状态,是否有任何预定义的语法或者我必须自己执行(睡眠)?
理想情况下,我希望在睡觉时从线程向另一个线程发送指示。
已编辑(2015-08-24) 我有两个主线程,一个用于通过网络发送数据,另一个用于从网络接收数据。除了抖动之外,接收线程还会进行验证和验证以及一些文件管理,这些文件管理会及时导致它被拖延。我喜欢做的是向发送者添加类似微睡眠的东西,以便接收者可以赶上。 sched_yield()在这种情况下无济于事,因为HW具有一个具有40多个内核的多核CPU。
答案 0 :(得分:2)
根据您在评论中的描述,您似乎正在尝试同步2个主题,以便其中一个不会落后于其他主题。
如果是这样的话,你就会以错误的方式解决这个问题。通过休眠进行同步很少是一个好主意,因为调度程序可能会导致不可预测的长延迟,导致其他(慢)线程在运行队列中保持停止状态而不进行调度。即使它在大多数时间都有效,它仍然是一种竞争条件,而且它是一个丑陋的黑客。
鉴于您的使用案例和限制因素,我认为您最好不要使用障碍(请参阅pthread_barrier_init(3)
)。 Pthread barrier允许您在代码中创建一个集合点,线程可以在其中找到它。
您将pthread_barrier_init(3)
作为初始化代码的一部分,指定将使用该障碍同步的线程数。在这种情况下,它是2。
然后,线程通过调用pthread_barrier_wait(3)
与其他人同步。该调用将阻塞,直到pthread_barrier_init(3)
中调用pthread_barrier_wait(3)
中指定的线程数,此时pthread_barrier_wait(3)
中阻塞的每个线程都将变为可运行且循环再次开始。从本质上讲,障碍创造了一个同步点,在每个人到达之前,任何人都无法前进。我认为这正是你正在寻找的。 p>
这是一个模拟快速发送方线程和慢速接收方线程的示例。它们都与屏障同步,以确保发送方在接收方仍在处理其他请求时不做任何工作。线程在其工作单元的末尾同步,但当然,您可以选择每个线程调用pthread_barrier_wait(3)
的位置,从而精确控制线程同步的时间(和位置)。
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
pthread_barrier_t barrier;
void *sender_thr(void *arg) {
printf("Entered sender thread\n");
int i;
for (i = 0; i < 10; i++) {
/* Simulate some work (500 ms) */
if (usleep(500000) < 0) {
perror("usleep(3) error");
}
printf("Sender thread synchronizing.\n");
/* Wait for receiver to catch up */
int barrier_res = pthread_barrier_wait(&barrier);
if (barrier_res == PTHREAD_BARRIER_SERIAL_THREAD)
printf("Sender thread was last.\n");
else if (barrier_res == 0)
printf("Sender thread was first.\n");
else
fprintf(stderr, "pthread_barrier_wait(3) error on sender: %s\n", strerror(barrier_res));
}
return NULL;
}
void *receiver_thr(void *arg) {
printf("Entered receiver thread\n");
int i;
for (i = 0; i < 10; i++) {
/* Simulate a lot of work */
if (usleep(2000000) < 0) {
perror("usleep(3) error");
}
printf("Receiver thread synchronizing.\n");
/* Catch up with sender */
int barrier_res = pthread_barrier_wait(&barrier);
if (barrier_res == PTHREAD_BARRIER_SERIAL_THREAD)
printf("Receiver thread was last.\n");
else if (barrier_res == 0)
printf("Receiver thread was first.\n");
else
fprintf(stderr, "pthread_barrier_wait(3) error on receiver: %s\n", strerror(barrier_res));
}
return NULL;
}
int main(void) {
int barrier_res;
if ((barrier_res = pthread_barrier_init(&barrier, NULL, 2)) != 0) {
fprintf(stderr, "pthread_barrier_init(3) error: %s\n", strerror(barrier_res));
exit(EXIT_FAILURE);
}
pthread_t threads[2];
int thread_res;
if ((thread_res = pthread_create(&threads[0], NULL, sender_thr, NULL)) != 0) {
fprintf(stderr, "pthread_create(3) error on sender thread: %s\n", strerror(thread_res));
exit(EXIT_FAILURE);
}
if ((thread_res = pthread_create(&threads[1], NULL, receiver_thr, NULL)) != 0) {
fprintf(stderr, "pthread_create(3) error on receiver thread: %s\n", strerror(thread_res));
exit(EXIT_FAILURE);
}
/* Do some work... */
if ((thread_res = pthread_join(threads[0], NULL)) != 0) {
fprintf(stderr, "pthread_join(3) error on sender thread: %s\n", strerror(thread_res));
exit(EXIT_FAILURE);
}
if ((thread_res = pthread_join(threads[1], NULL)) != 0) {
fprintf(stderr, "pthread_join(3) error on receiver thread: %s\n", strerror(thread_res));
exit(EXIT_FAILURE);
}
if ((barrier_res = pthread_barrier_destroy(&barrier)) != 0) {
fprintf(stderr, "pthread_barrier_destroy(3) error: %s\n", strerror(barrier_res));
exit(EXIT_FAILURE);
}
return 0;
}
请注意,正如pthread_barrier_wait(3)
的联机帮助页中所指定的,一旦所需的线程数调用pthread_barrier_wait(3)
,屏障状态将重置为上次调用{后使用的原始状态{1}},这意味着屏障原子地解锁并重置状态,因此它总是为下一个同步点做好准备,这很棒。
完成障碍后,请勿忘记使用pthread_barrier_init(3)
释放相关资源。