关于Realm上的线程和DataConsistent的一点混乱

时间:2017-08-16 01:51:20

标签: objective-c multithreading realm

  

您可以让任意数量的线程并行处理同一个Realms,并且由于它们都有自己的快照,因此它们永远不会导致彼此看到不一致的状态

考虑写入线程是否改变了某些值并且比读取线程更快地完成,但是,由于读取线程有自己的快照,因此它不会改变,因为在写入线程上做了什么,但是如果读取线程的操作是基于最新的值,所以这意味着读取线程无法正常运行? thx求助。

我的测试演示来描述我的困惑

an image that contains my test demo to describe my confusion

2 个答案:

答案 0 :(得分:2)

由于"不一致",文档意味着"部分修改"。它们无法进行部分修改,因为您始终可以看到由事务更改创建的特定版本。

但是,跨线程不会立即进行更新。

  

因为读取线程有自己的快照,所以它不会因为在写入线程上做了什么而改变,但是如果读取线程的操作基于最新值,那么它就是'那意味着读线程无法正常运行?

是的,这正是读取线程应该使用收集通知的原因。

// from https://realm.io/docs/objc/latest/#collection-notifications
- (void)viewDidLoad {
  [super viewDidLoad];

  // Observe RLMResults Notifications
  __weak typeof(self) weakSelf = self;
  self.notificationToken = [[Person objectsWhere:@"age > 5"] addNotificationBlock:^(RLMResults<Person *> *results, RLMCollectionChange *changes, NSError *error) {
    if (error) {
      NSLog(@"Failed to open Realm on background worker: %@", error);
      return;
    }

    UITableView *tableView = weakSelf.tableView;
    // Initial run of the query will pass nil for the change information
    if (!changes) {
      [tableView reloadData];
      return;
    }

    // Query results have changed, so apply them to the UITableView
    [tableView beginUpdates];
    [tableView deleteRowsAtIndexPaths:[changes deletionsInSection:0]
                     withRowAnimation:UITableViewRowAnimationAutomatic];
    [tableView insertRowsAtIndexPaths:[changes insertionsInSection:0]
                     withRowAnimation:UITableViewRowAnimationAutomatic];
    [tableView reloadRowsAtIndexPaths:[changes modificationsInSection:0]
                     withRowAnimation:UITableViewRowAnimationAutomatic];
    [tableView endUpdates];
  }];
}
- (void)dealloc {
  [self.notificationToken stop];
}

除此之外,交易始终&#34;创建最新版本&#34; (并且一次只能有一个事务),因此写事务中的查询不能过时。

dispatch_async(writeQueue, ^{
    [[RLMRealm defaultRealm]] transactionWithBlock:^{
         Cinema* b = [Cinema allObjects].firstObject; // query cannot be out of date
         ...

显然, NOT 意味着你应该在UI线程上执行事务只是为了碰撞它的版本。使用通知令牌。

答案 1 :(得分:1)

是的,这是正确的。如果要确保始终从Realm获取一致的数据,请不要从单独的线程同时访问它,因为在一个线程上完成的写入事务不会反映在另一个线程上。这也是您的示例中可以看到的行为。

除非您有大量的对象要从中读取/写入,否则也不需要异步访问域。如果你想使用如此大量的对象,你的查询/写入事务需要几秒钟,因此同步执行它们会阻止UI更新太长时间,请确保只从单个线程访问Realm并确保你的异步读/写操作没有并行运行。