如何使用GCD轻量级事务锁定资源?

Pro*_*ber 3 concurrency opengl-es grand-central-dispatch ios

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

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

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

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

但似乎我无法使用GCD将值入主线程,同时阻塞执行绘图代码的队列.dispatch_synch没有返回值,但我希望能够两帧的绘图之间准确地访问表示值,以便进行读取和写入.

barrier他们在谈论这件事吗?这是如何运作的?

jkh*_*jkh 5

这就是异步编写器/同步读取器模型旨在实现的目标.假设你有一个ivar(为了讨论的目的,让我们假设你已经进一步将所有的ivars封装成一个单独的结构,只是为了简单起见:

struct {
  int x, y;
  char *n;
  dispatch_queue_t _internalQueue;
} myIvars;
Run Code Online (Sandbox Code Playgroud)

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

现在,写一个值:

dispatch_async(myIvars._internalQueue, ^{ myIvars.x = 10; });
dispatch_async(myIvars._internalQueue, ^{ myIvars.n = "Hi there"; });
Run Code Online (Sandbox Code Playgroud)

阅读一篇:

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

使用内部队列可确保所有内容都经过适当的序列化,并且写入可以异步发生,但读取等待所有挂起的写入完成后再返回值.许多"GCD感知"数据结构(或具有内部数据结构的例程)将串行队列作为实现细节包含在此目的中.