gpt4 book ai didi

grand-central-dispatch - dispatch_semaphore_wait 不是先进先出吗?

转载 作者:行者123 更新时间:2023-12-04 00:18:04 24 4
gpt4 key购买 nike

documentation for dispatch_semaphore_wait说它“以 FIFO 顺序等待信号”。但在这个例子中似乎没有——有人可以解释一下吗?

示例:

#include <dispatch/dispatch.h>
#include <stdio.h>

dispatch_queue_t q1, q2;
dispatch_semaphore_t sem;
int g_call;

void do_work(void)
{
int s = 0;
int i;
for (i = 0; i < 100000000; ++i)
++s;
}

void f1(int call)
{
__block int waited = 0;
dispatch_async(q1, ^{
while (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC/1000)))
waited = 1;
printf("1:%d %s\n", call, waited ? "waited" : "");
do_work();
dispatch_semaphore_signal(sem);
});
}

void f2(int call)
{
__block int waited = 0;
dispatch_async(q2, ^{
while (dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC/1000)))
waited = 1;
printf("\t\t2:%d %s\n", call, waited ? "waited" : "");
do_work();
dispatch_semaphore_signal(sem);
});
}

int main(int argc, char **argv)
{
q1 = dispatch_queue_create(NULL, NULL);
q2 = dispatch_queue_create(NULL, NULL);
sem = dispatch_semaphore_create(1);
g_call = 0;

dispatch_queue_t q_global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, q_global);
const uint64_t DELAY = 10;
dispatch_source_set_event_handler(timer, ^{
f1(g_call);
f2(g_call);
++g_call;
dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, DELAY), 0, 0);
});
dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, DELAY), 0, 0);
dispatch_resume(timer);

sleep(3);
}

预期输出:

1:0
2:0
1:1
2:1
1:2
2:2
...

实际输出(一个例子):

1:0
1:1
...
1:14
2:0 waited
2:1
...

编辑:如果 q1 和 q2 不是串行队列,而是设置为全局队列,则实际输出:

1:0 
2:8 waited
1:3 waited
1:4 waited
2:3 waited
1:6 waited
1:9 waited
2:9 waited
2:21
1:28 waited

(有时完美,但有时像这样很奇怪。)

最佳答案

dispatch_queue_create 创建一个串行队列,然后串行队列创建一个 pthread 线程(我不太确定...)。

并且 dispatch_semaphore_wait 使用自旋锁来获取信号量以提高性能。这意味着它不是像 pthread_mutex_lock 那样的上下文切换点。它不会如此频繁地切换上下文。

如果您使用全局队列,您的代码将按照您的预期输出(但并不完全相同)。因为全局队列使用的是pthread workqueue。切换上下文的行为不同于 pthread 线程的行为。

q1 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
q2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

已编辑:

全局队列顺序执行给定的任务,但这些任务是并发执行的,输出顺序可能因上下文切换而异。此外,代码的计时器每 10 纳秒触发一次,并发执行的任务过多。

另一个简单的例子,

dispatch_queue_t queue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(10, queue, ^(size_t index) {
printf("%zu\n", index);
});

在我的 8 核 MacBook Pro 上:

4
2
0
6
3
1
5
8
9
7

关于grand-central-dispatch - dispatch_semaphore_wait 不是先进先出吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6601243/

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