1

假设我创建了一个对象myObject,并且在某个时候我希望它被锁定,直到我收到通知。收到通知后,我想解锁它。这可以使用 GCD 完成还是我必须使用锁或其他东西?谢谢!

编辑:所以这是我要解决的确切问题。我有一个线程正在将照片写入ALAssetsLibrary. UI 正在使用ALAssets以显示库中的照片。我的问题是:writeImageDataToSavedPhotosAlbum更改库导致所有ALAssets内容无效,因此如果我的第二个线程正在从库中加载照片,它可能会失败(并且经常会失败)。我读到解决这个问题的唯一方法是在 之后加载ALAssetsLibraryChangedNotification,所以我试图让库从我写到它的那一刻到我收到通知的那一刻都无法访问。

4

1 回答 1

0

当您应该从队列的角度考虑问题时,您正在从锁的角度考虑问题。给定一些共享的“资源”,您想要做的是这样的事情(未经测试)。这只是方法的草图,但它应该让你走上正确的轨道。您应该尽可能避免使用锁。

@implementation Resource

- (id)init {
...
  // Assuming you are the only one who can possibly change the library
  // See suspendQueue for related code
  [[NSNotificationCenter defaultCenter] addObserver:self 
                                          selector:@(resumeQueue:) ...
                                              name:...thenoteification...];

// Always request things synchronously on the queue
- (Something *)somethingForStuff:(Stuff *)stuff {
  __block Something *result;
  dispatch_sync(self.queue, ^{
    result = GetSomethingForStuffFromMe(stuff);
  });
  return result;
}

// Always change things asynchronously on the queue with a barrier
// And in your case, suspend the queue to lock it until done
- (void)setSomething:(Something *)something forStuff:(Stuff *)stuff {
  dispatch_barrier_async(self.queue, ^{
    SetSomethingForStuff(something, stuff);
    [self suspendQueue];
  });
}

// You'll need to think this through a little bit. It depends on your exact model.
// I'm using isSuspended really just as an error-check to make sure something
// hasn't gone wrong.
- (void)suspendQueue {
  NSAssert(! self.isSuspended, @"In this example, I don't allow recursive suspension.");
  [self.queue suspend];
  self.suspended = YES;
}

// This code assumes you're the only one who can cause this notification.
// You may need to change things a little if that's not true
- (void)resumeQueue {
  NSAssert(self.isSuspended, @"We should only ever see this notification if we caused it");
  self.suspended = NO;
  [self.queue resume];
}
于 2012-08-14T21:16:58.917 回答