使用Xcode 9工具查找运行时错误
可能的情况
1 –数据竞赛
在多个线程之间共享的任何可变数据都需要访问同步。 如果在共享的可变变量上缺少同步 ,则意味着您存在数据竞争。 在存在数据争用的情况下,我们的程序可能会发生内存损坏和崩溃。 这些问题适用于C语言,也适用于Swift代码。 因此,让我们看一下Swift中的示例。
在这种情况下,我们有一个名为EventLog的类,它仅具有一个简单的名为log的函数,该函数将一些文本消息输出到输出中。 但是它也跟踪哪个是调用该log方法的最后一个事件源。 它将信息保存到一个名为lastEventSource的存储属性中,该属性是一个可选变量,在开始时为nil,但是一旦有人调用log,就会使用该特定日志源完美填充该信息。
现在让我们说我们有两个线程都试图同时调用该log方法。 假设第一个线程是我们的网络子系统,并且记录了一些下载已完成。 当第二个线程(代表我们的数据库子系统)正在记录查询已完成时:
那是一场数据竞赛,因为我们正在同时访问相同的内存位置。 Thread Sanitizer将对此发出警告!
要解决此问题,我们需要引入同步,最简单的方法是使用串行调度队列。
现在,由于此队列是串行的,因此一次只能执行一个工作项。 因此,如果将log函数的主体包装到queue.async中,将提供正确的同步。 并请注意,我在这里使用async是因为我们不需要等待该函数完成,因为该函数不会提供任何结果,因此等待它是没有意义的。 因此,这不仅解决了该问题,而且还提高了性能,因为现在无论呼叫日志的人都不再需要等待此打印完成。
这样,整个类现在都是线程安全的,我们可以从多个线程调用log 。 由Grand Central Dispatch或GCD提供的Dispatch队列在Swift中很容易获得,它们应该是同步的首选。 即使还有其他提供同步的机制,GCD也非常轻巧,并且可以从Swift轻松使用。
提示:一个好主意是将数据与串行调度队列相关联,并且仅访问这些队列中的数据,这将确保您仅以同步方式使用数据。
- 在GLKViewController中使用glTexImage2D的EXC_BAD_ACCESS
- embedded到容器视图中的tableView顶部的空白区域
- 如何从一个视图控制器导航到另一个视图控制器button点击?
- iOS – 在仅IPv6networking上获取设备的DNS服务器地址
- 使用UICollectionViewCell中的UICollectionView
- NSMutableDictionary:将变异方法发送给不可变对象
- 如何在iOS swift中实现评论和回复系统
- 滚动时,UITableViewCell detailTextLabel消失
- 在Swift数组中find第一个元素匹配条件(例如EKSource)