并发队列中的原子属性

关于原子如何工作的研究~~~

从我关于引用计数的文章中,我对原子的工作原理以及它不是线程安全的方法很感兴趣。 因此,本文致力于并发操作中有关原子属性的一些示例代码。

并发队列可以包含多个任务,但是任务的顺序由操作系统管理,这将在后面显示。

根据Apple官方网站,我们可以创建三种主要的Dispatch Queue类型:

并发队列可以很容易地创建如下:

现在,我将创建一个将在队列上运行的函数:

为了在队列上运行testRunner ,您需要通过dispatch_async调用它们:

由于testRunner只循环一次,因此OS可以轻松地连续照顾它们,显示NS​​Logs:

但是,如果将循环增加到5,则它们将不会连续运行:

为了证明它们是不同的线程,只需在调用该函数的行上放置一个断点,然后您可以检查正在运行的线程:

由于操作是由CPU管理的,因此可能有机会在同一线程上进行操作。 但是,当线程大得多(i <500)时,看起来它们有更大的机会在不同的线程上进行操作。

[我仍然需要阅读更多有关此内容的信息,但是如果您有任何想补充的内容,请给我一个共同的名字,一千个感谢^^]

原子属性怎么样?

在这里,我创建了一个名为AtomicModel的类,该类包含两个属性: atomicStringnonAtomicString

在功能runAtomicThreads中 ,创建并发调度,并创建两个线程,一个线程调用[self atomicSetter],另一个调用[self atomicGetter]。

基本上, atomicSetter的计数从0到100000,并将atomicString设置为偶数为“很长的字符串”,而奇数为“ string”。

尽管atomicGetter可以做同样的事情,但是当atomicString.length≥10时,它将创建一个subStr

如果您运行该代码,则当for循环重复一个较小的数字时,您将看到没有错误。 但是,当重复计数增加时,您将有机会反弹到错误:

那么到底发生了什么呢?

为了帮助我理解发生了什么,我在线程B中获取subStr之前和之后都记录了atomicString

从线程B打印出的最后一句话看,线程B似乎认为atomicString ==“一个很长的字符串”

让我们看看线程A对此有何看法。

显然,线程A和线程B在atomicString应该是什么值上存在分歧。

因此,当线程B认为atomicString .length≥10时 ,线程A将其更改为长度小于10的“字符串”。 这导致代码崩溃。

结果,这证明原子属性不是线程安全的。

当使用非原子属性时,也会发生相同的错误,唯一的区别是非原子比原子快得多。