- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
假设您想在 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/
在 java 中不使用“同步”关键字的情况下,是否有其他方法可以同步类或方法? 谢谢, 马利卡琼·科卡塔努尔 最佳答案 您可能想查看并发包中引入的对 JDK 5 的更改。 http://java.su
第 1 部分: 假设下面这段代码 void method1(){ synchronized (lockObject){ method2(); System.ou
我有一个 REST 服务器和一个在移动设备上运行的客户端应用程序。客户端有一些数据并希望从服务器获取数据更新。如何以 RESTful 方式在单个事务中执行此操作? 假设客户有以下元素: widge
我有一个多线程 Java 应用程序。在一种方法中,需要同步一个 ArrayList。由于 arrayList 不是线程安全的,所以我必须使用同步。问题是 ArrayList 类型的对象不是对象的成员变
我正在阅读 Android 示例中的 BluetoothChatService.java 文件,有一件事特别让我感到困惑。 方法在多个位置访问静态成员,并且定义为同步。 在另一部分中,正在访问同一个静
我知道为了实现线程安全和同步,我们使用同步块(synchronized block)或方法。 但我无法理解声明- “Java 中的同步块(synchronized block)在某些对象上同步 ” 任
在 Scala 中使用 JDBC 的示例中,有以下代码: this.synchronized { if (!driverLoaded) loadDriver() } 为什么this.synchro
abstract class A { protected abstract int isRunning(); public void concreteMethod() { synchr
有谁可以分享一下他们的经验吗?“我们什么时候在同步方法和同步块(synchronized block)之间进行调用”有任何性能问题吗? 最佳答案 When do we make a call to u
这是我之前问题的后续问题,Is this variable being safely accessed by using synchronization? 对于下面的程序, Class SubClas
我目前正在为 N 体问题实现多线程版本的 Barnes-Hut 算法。虽然该算法有效,但它不是很优化,我正在尝试减少我的程序的运行时间。 我已经确保有多个线程可以准确地找到我正在使用的空间的边界,并意
我有这门课: public class MyClass { public MyClass(){} public void actionA(){ synchronized
又是一个关于ArrayList和synchronize的问题。 我只想知道这段代码到底做了什么: ArrayList list = ....; synchronized (list) { if
我可以在另一个同步块(synchronized block)中包含同步块(synchronized block)以同步另一个对象吗? 例子: synchronized(myObjetc1){
public class ObjectCounter { private static long numOfInstances = 0; public ObjectCounter(){
我在某处读到,对于 various reasons 应该避免 synchronized(this) .然而,我遇到的一些值得尊敬的代码在构造函数中使用了以下内容: public SomeClass(C
Java 为同步代码的关键部分提供了一种非常方便的习惯用法: synchronized(someObject) { // do something really important all b
我有一个 WeakReference 的 Collections.synchronizedList,_components; 我写了类似下面的内容,希望编译者会提示: public boolean a
使用下面两个版本的Singleton Classes有什么区别 首先我使用的是synchronized(Singleton.class) 在第二个我使用同步(Obj)//第一种类型 公共(public
我正在查看 DatagramSocket 的源代码,我发现了这个: public void disconnect() { synchronized (this) { if (i
我是一名优秀的程序员,十分优秀!