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
Cocoa 如果我不';在创建它们的线程上不显式访问它们?_Cocoa_Multithreading_Macos_Core Data - Fatal编程技术网

Cocoa 如果我不';在创建它们的线程上不显式访问它们?

Cocoa 如果我不';在创建它们的线程上不显式访问它们?,cocoa,multithreading,macos,core-data,Cocoa,Multithreading,Macos,Core Data,我正在开发cocoa软件,为了在大规模数据导入(核心数据)期间保持GUI的响应性,我需要在主线程之外运行导入 如果线程运行时我没有显式访问这些对象,那么即使我在主线程中创建了这些对象而不使用锁,也可以安全地访问它们。使用锁的全部目的是确保两个线程不尝试访问同一资源。如果您可以通过其他机制保证这一点,那就试试吧。即使是安全的,但在线程之间使用共享数据而不同步对这些字段的访问不是最佳做法。哪个线程创建了对象并不重要,但如果有多个执行行(线程/进程)同时访问对象,则会导致数据不一致 如果您绝对确定只有

我正在开发cocoa软件,为了在大规模数据导入(核心数据)期间保持GUI的响应性,我需要在主线程之外运行导入


如果线程运行时我没有显式访问这些对象,那么即使我在主线程中创建了这些对象而不使用锁,也可以安全地访问它们。

使用锁的全部目的是确保两个线程不尝试访问同一资源。如果您可以通过其他机制保证这一点,那就试试吧。

即使是安全的,但在线程之间使用共享数据而不同步对这些字段的访问不是最佳做法。哪个线程创建了对象并不重要,但如果有多个执行行(线程/进程)同时访问对象,则会导致数据不一致


如果您绝对确定只有一个线程会访问这个对象,那么不同步访问是安全的。即便如此,我还是宁愿现在就将同步放在代码中,也不愿等到应用程序中的更改使第二个线程共享相同的数据而不考虑同步访问。

是的,这是安全的。一种非常常见的模式是创建一个对象,然后将其添加到队列或其他集合中。第二个“消费者”线程从队列中获取项目并对其进行处理。在这里,您需要同步队列,但不需要同步添加到队列中的对象


只是同步所有事情并希望一切顺利不是一个好主意。您需要非常仔细地考虑您的设计以及哪些线程可以作用于您的对象。

是的,您可以这样做,它将是安全的

。。。 直到第二个程序员出现并且不理解您所做的相同假设。第二个(或第三个、第四个、第五个……)程序员可能开始以非安全的方式(在创建者线程中)使用对象。造成的问题可能非常微妙,很难追踪。仅出于这个原因,并且由于在多个线程中使用这个对象是如此诱人,我会使这个对象线程安全

为了澄清,(感谢那些留下评论的人):

我所说的“线程安全”是指通过编程设计一个方案来避免线程问题。我的意思不一定是在你的物体周围设计一个锁定方案。您可以在您的语言中找到一种方法,使在creator线程中使用对象非法(或非常困难)。例如,将creator线程中的作用域限制为创建对象的代码块。创建后,将对象传递给用户线程,确保创建者线程不再引用它

例如,在C中++

void CreateObject()
{
    Object* sharedObj = new Object();
    PassObjectToUsingThread( sharedObj); // this function would be system dependent
}

然后,在你的创建线程中,在创建之后,你就不再有访问对象的权限,将责任传递给使用线程。

两个要考虑的事情是:

  • 您必须能够保证对象在对其他线程可用之前已完全创建和初始化
  • 必须有某种机制,通过这种机制,主(GUI)线程可以检测到数据已经加载,并且一切正常。为了线程安全,这将不可避免地涉及某种类型的锁定

我认为这对于由CoreData NSManagedObjectContext管理的NSManagedObjects(或子类)是不安全的。通常,CoreData可能会对托管对象的状态执行许多棘手的操作,包括在单独的线程中触发与这些对象相关的错误。特别是,
[NSManagedObject initWithEntity:insertIntoManagedObjectContext:
(从OS X 10.5开始为NSManagedObject指定的初始值设定项)不能保证返回的对象可以安全地传递到其他线程


使用多线程的CoreData在苹果的

对于核心数据,您应该有一个单独的托管对象上下文用于导入线程,连接到同一协调器和持久存储。您不能简单地将在主线程使用的上下文中创建的对象扔到另一个线程中,并期望它们工作。此外,您不能为此自行锁定;您必须至少锁定对象所在的托管对象上下文(视情况而定)。但是,如果这些对象由视图和控件绑定,则没有可以添加上下文锁定的“挂钩”

没有免费的午餐

Ben Trumbull解释了为什么需要使用单独的上下文,以及为什么“仅仅阅读”不像你想象的那么简单或安全。(整个主题非常棒。)他正在讨论企业对象框架和WebObjects,但他的建议也完全适用于核心数据。在他的信息中,只需将“EC”替换为“NSManagedObjectContext”,将“EOF”替换为“核心数据”


核心数据中线程之间共享数据的问题的解决方案,就像之前的企业对象框架一样,是“不要”。如果您进一步考虑了这个问题,并且确实必须在线程之间共享数据,那么解决方案就是在线程隔离的上下文中保持独立的对象图,并使用来自一个上下文的save通知中的信息告诉另一个上下文重新获取什么。是专门为支持这种使用而设计的。

大多数语言没有很多语言级别的工具来帮助进行并发编程。我们几乎被文档和开发人员交流所困扰。我仍然认为让对象线程安全“以防万一”是个坏主意,但也许让对象不可变是最好的选择。一般来说,你不能笼统地“让对象线程安全”。对象通常是更大的对象图的一部分,通常整个图需要事务语义。那个