jjzjj

ios - 有没有办法让 synchronized 关键字不阻塞主线程

coder 2024-01-15 原文

假设您想在 iOS 应用程序的后台做很多事情,但您对其进行了适当的编码,以便创建线程(例如使用 GCD)来执行此后台事件。

现在,如果您需要在某个时刻写入更新变量,但此更新可能发生或您创建的任何线程发生,该怎么办。

你显然想保护那个变量,你可以使用关键字 @synchronized 为你创建锁,但这里有问题(摘自 Apple 文档)

The @synchronized() directive locks a section of code for use by a single thread. Other threads are blocked until the thread exits the protected code—that is, when execution continues past the last statement in the @synchronized() block.

这意味着如果您同步了一个对象并且两个线程同时写入它,即使是主线程也会阻塞,直到两个线程都完成写入数据。

展示所有这些的代码示例:

// Create the background queue
dispatch_queue_t queue = dispatch_queue_create("synchronized_example", NULL);

// Start working in new thread
dispatch_async(queue, ^
               {                   
                   // Synchronized that shared resource
                   @synchronized(sharedResource_)
                   {   
                       // Write things on that resource
                       // If more that one thread access this piece of code:
                       // all threads (even main thread) will block until task is completed.
                       [self writeComplexDataOnLocalFile];
                   }                         
               });

// won’t actually go away until queue is empty
dispatch_release(queue);

所以问题很简单:如何克服这个问题?我们如何才能安全地在除主线程之外的所有线程上添加锁,我们知道在这种情况下不需要被阻塞?

编辑澄清

正如你们中的一些人评论的那样,只有两个试图获取锁的线程应该阻塞,直到它们都完成为止,这似乎是合乎逻辑的(这显然是我最初在使用同步时的想法)。

然而,在实际情况下测试,似乎并非如此,主线程似乎也受到锁定的影响。

我使用这种机制在单独的线程中记录内容,这样 UI 就不会被阻塞。但是当我进行大量日志记录时,UI(主线程)显然受到了很大影响(滚动不那么流畅)。

所以这里有两个选择:要么后台任务太重,甚至主线程也会受到影响(我怀疑),要么 synchronized 在执行锁定操作时也会阻塞主线程(我正在开始重新考虑)。

我将使用 Time Profiler 进行更深入的挖掘。

最佳答案

我相信您误解了您从 Apple 文档中引用的以下句子:

Other threads are blocked until the thread exits the protected code...

这并不意味着所有线程都被阻塞,它只是意味着所有试图在同一对象(您的示例中的 _sharedResource)上进行同步的线程都被阻塞。

以下引述摘自 Apple 的 Thread Programming Guide ,这清楚地表明只有在同一对象上同步的线程才会被阻塞。

The object passed to the @synchronized directive is a unique identifier used to distinguish the protected block. If you execute the preceding method in two different threads, passing a different object for the anObj parameter on each thread, each would take its lock and continue processing without being blocked by the other. If you pass the same object in both cases, however, one of the threads would acquire the lock first and the other would block until the first thread completed the critical section.

更新:如果您的后台线程正在影响界面的性能,那么您可能需要考虑让后台线程休眠。这应该让主线程有时间更新 UI。

我知道你正在使用 GCD,但是,例如,NSThread 有几个方法可以挂起线程,例如-sleepForTimeInterval:。在 GCD 中,您可能只需调用 sleep()

或者,您可能还想考虑将线程优先级更改为较低的优先级。同样,NSThread 具有用于此目的的 setThreadPriority:。在 GCD 中,我相信您只会为分派(dispatch)的 block 使用低优先级队列。

关于ios - 有没有办法让 synchronized 关键字不阻塞主线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10298762/

有关ios - 有没有办法让 synchronized 关键字不阻塞主线程的更多相关文章

  1. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  2. ruby-on-rails - rails 目前在重启后没有安装 - 2

    我有一个奇怪的问题:我在rvm上安装了ruby​​onrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(

  3. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  4. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  5. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  6. 没有类的 Ruby 方法? - 2

    大家好!我想知道Ruby中未使用语法ClassName.method_name调用的方法是如何工作的。我头脑中的一些是puts、print、gets、chomp。可以在不使用点运算符的情况下调用这些方法。为什么是这样?他们来自哪里?我怎样才能看到这些方法的完整列表? 最佳答案 Kernel中的所有方法都可用于Object类的所有对象或从Object派生的任何类。您可以使用Kernel.instance_methods列出它们。 关于没有类的Ruby方法?,我们在StackOverflow

  7. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  8. ruby-on-rails - 有没有办法为 CarrierWave/Fog 设置上传进度指示器? - 2

    我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r

  9. ruby - 没有类方法获取 Ruby 类名 - 2

    如何在Ruby中获取BasicObject实例的类名?例如,假设我有这个:classMyObjectSystem我怎样才能使这段代码成功?编辑:我发现Object的实例方法class被定义为returnrb_class_real(CLASS_OF(obj));。有什么方法可以从Ruby中使用它? 最佳答案 我花了一些时间研究irb并想出了这个:classBasicObjectdefclassklass=class这将为任何从BasicObject继承的对象提供一个#class您可以调用的方法。编辑评论中要求的进一步解释:假设你有对象

  10. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

随机推荐