objective-c – 在调度队列中修改父作用域中的数据

根据并发编程指南:

When blocks are added to a dispatch queue, these values must typically be left in a read-only format. However, blocks that are executed synchronously can also use variables that have the __block keyword prepended to return data back to the parent’s calling scope.

我一直在改变在队列外部创建的变量,但是我从来没有用__block指定它们,所以我想知道究竟何时或为什么需要它.或者是实例变量总是固有地可以被块改变,就好像它们从幕后分配给它们__block一样?

更新:我也应该添加我正在使用异步队列,而上面说只能在同步队列中改变变量(使用__block)

最佳答案 在块中访问类的实例变量iVar将被编译器解释为self-> iVar.因此,块捕获自身,不会被修改.

我确信__block修饰符也适用于dispatch_async,因此这可能是文档错误.

添加

以下示例显示__block变量如何与dispatch_async一起使用:

dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
__block int total = 0;
printf("address of total: %p\n", &total);

// dispatch some (concurrent) blocks asynchronously:
dispatch_async(queue, ^{
    OSAtomicAdd32(5, &total);
});
dispatch_async(queue, ^{
    OSAtomicAdd32(7, &total);
});

// Wait for all blocks to complete:
dispatch_barrier_sync(queue, ^{ });

printf("address of total: %p\n", &total);
printf("total=%d\n", total);

输出:

address of total: 0x7fff5fbff8f0
address of total: 0x100108198
total=12

可以看到,在执行块时,total会从堆栈复制到堆栈.

添加

我刚刚在Blocks Programming Guide中找到了它.它解释了为什么将__block变量与异步块一起使用没有问题.

__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or
created within the variable’s lexical scope. Thus, the storage will
survive the destruction of the stack frame if any copies of the blocks
declared within the frame survive beyond the end of the frame (for
example, by being enqueued somewhere for later execution). Multiple
blocks in a given lexical scope can simultaneously use a shared
variable.

As an optimization, block storage starts out on the
stack—just like blocks themselves do. If the block is copied using
Block_copy (or in Objective-C when the block is sent a copy),
variables are copied to the heap. Thus, the address of a __block
variable can change over time .

点赞