3

我正在尝试使用 GCD 作为数十个原子属性的替代品。我记得在 WWDC 上,他们谈到 GCD 可以用于高效的事务锁定机制。

在我的 OpenGL ES runloop 方法中,我将所有绘图代码放在一个由dispatch_sync自定义创建的串行队列执行的块中。运行循环由 CADisplayLink 调用,据我所知,它发生在主线程上。

有 ivars 和属性既可用于绘图,也可用于控制将要绘制的内容。问题是必须有一些锁定以防止并发问题,以及在两个绘制帧之间从主线程以事务方式查询和修改 OpenGL ES 场景状态的方法。

通过在该串行队列上执行一个块,我可以使用 GCD 以事务方式修改一组属性。

但似乎我无法使用 GCD 将值入主线程,同时阻塞执行绘图代码的队列。dispatch_synch没有返回值,但我想在两个帧的绘制之间准确地访问表示值,用于读取和写入。

barrier他们说的就是这个吗?这是如何运作的?

4

2 回答 2

5

这就是异步写入器/同步读取器模型旨在完成的任务。假设您有一个 ivar(为了讨论的目的,我们假设您已经走得更远了,并将所有 ivar 封装到一个结构中,只是为了简单起见:

struct {
  int x, y;
  char *n;
  dispatch_queue_t _internalQueue;
} myIvars;

让我们进一步假设(为简洁起见)您已经在 dispatch_once() 中初始化了 ivars,并在代码的前面使用 dispatch_queue_create() 创建了 _internalQueue 作为串行队列。

现在,写一个值:

dispatch_async(myIvars._internalQueue, ^{ myIvars.x = 10; });
dispatch_async(myIvars._internalQueue, ^{ myIvars.n = "Hi there"; });

并阅读一个:

__block int val; __block char *v;
dispatch_sync(myIvars._internalQueue, ^{ val = myIvars.x; });
dispatch_sync(myIvars._internalQueue, ^{ v = myIvars.n; })

使用内部队列可确保一切都被适当地序列化,并且写入可以异步发生,但读取会等待所有挂起的写入完成,然后再将值返回给您。许多“GCD 感知”数据结构(或具有内部数据结构的例程)将串行队列作为实现细节用于此目的。

于 2012-09-27T01:26:11.100 回答
1

dispatch_sync 允许您指定第二个参数作为完成块,您可以在其中从串行队列中获取值并在主线程上使用它们。所以它看起来像

dispatch_sync(serialQueue,^{
    //execute a block
    dispatch_async(get_dispatch_main_queue,^{

        //use your calculations here
    });
});

串行队列自己处理并发部分。因此,如果另一部分试图同时访问相同的代码,它将由队列本身处理。希望这没什么帮助。

于 2012-09-26T15:57:54.477 回答