Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 使用GCD的递归同步_Objective C_Multithreading_Synchronization_Grand Central Dispatch - Fatal编程技术网

Objective c 使用GCD的递归同步

Objective c 使用GCD的递归同步,objective-c,multithreading,synchronization,grand-central-dispatch,Objective C,Multithreading,Synchronization,Grand Central Dispatch,我有一些模型类需要同步。有一个类型为Library的主对象,其中包含多个Album对象(例如,想象一个音乐库)。通过实现NSCoding协议,库和相册都支持序列化。我需要同步修改库与专辑的修改和两个类的序列化,这样我就知道更新不会在彼此的脚趾上踩下,而且我不会在更新的中间序列化对象。 我想我应该给所有对象传递一个共享调度队列,dispatch\u async所有setter代码和dispatch\u syncgetter。这很简单,但不起作用,因为程序流是递归的: // In the Libra

我有一些模型类需要同步。有一个类型为
Library
的主对象,其中包含多个
Album
对象(例如,想象一个音乐库)。通过实现
NSCoding
协议,库和相册都支持序列化。我需要同步修改库与专辑的修改和两个类的序列化,这样我就知道更新不会在彼此的脚趾上踩下,而且我不会在更新的中间序列化对象。 我想我应该给所有对象传递一个共享调度队列,
dispatch\u async
所有setter代码和
dispatch\u sync
getter。这很简单,但不起作用,因为程序流是递归的:

// In the Library class
- (void) encodeWithCoder: (NSCoder*) encoder
{
    dispatch_sync(queue, ^{
        [encoder encodeObject:albums forKey:…];
    });
}

// In the Album class, same queue as above
- (void) encodeWithCoder: (NSCoder*) encoder
{
    dispatch_sync(queue, ^{
        [encoder encodeObject:items forKey:…];
    });
}
现在序列化库会触发相册序列化,因为这两种方法都在同一队列上使用
dispatch\u sync
,所以代码会死锁。我在某处见过这种模式:

- (void) runOnSynchronizationQueue: (dispatch_block_t) block
{
    if (dispatch_get_current_queue() == queue) {
        block();
    } else {
        dispatch_sync(queue, block);
    }
}

它有意义吗?它会工作吗?它安全吗?有更简单的同步方法吗?

有关GCD中递归锁的说明,请参阅的递归锁部分。简而言之,当出现类似情况时,重新考虑对象层次结构通常是一个好主意

重构代码后,您还可以使用
dispatch\u set\u target\u queue()
来控制执行层次结构(将下级队列定位在更高级别的队列中),从而使需要控制的是操作而不是对象,但这也是假设您不能简单地使用完成回调来实现相同的同步效果(坦白地说,这是更推荐的,因为抽象队列层次结构可能很难概念化和调试)


我知道这并不是你想要的答案,但你在GCD中处于一种“你无法从这里到达那里”的状态,在这种情况下,几乎肯定有必要从根本上重新思考如何以“GCD方式”做事。

这不是我希望听到的答案,但却是一个好答案:)谢谢。