Swift单线程内存访问冲突

同时有多个访问访问同一块内存,其中一个是写访问。就会出现内存冲突。

出现冲突需要满足3个条件:

  • 至少一个是写访问或者非原子操作
  • 访问同一块内存
  • 访问时间有交叉

inout修饰函数参数带来的冲突
inout参数是一个长时写访问,访问从所有的非inout参数被评估之后开始,到函数执行完毕。
把一个外部变量a作为参数传递给函数,然后在函数内读a,就会发生冲突,此时a有两个访问,一个读,一个写。满足出现冲突的3个条件

把同一个变量作为参数传递给一个函数的多个inout参数。同一个变量就是同一块内存,多个inout参数 就是多个写访问,在一个函数里,所以在同一时间。满足冲突3条件

struct的mutating函数会对self有写访问。所以调用struct的mutating函数会有机会出现冲突。比如sturct A有一个mutating func函数,这个函数有一个inout参数,这个参数就是struct A 类型,a是 A的一个实例,然后调用函数func时,把a作为参数。这会儿就会出现冲突。

访问property时也会出现,因为struct, tuple,enumeration等类型是值类型,所以访问其中的peroperty时就是访问整个实例,如以下代码

func swap(x: inout Int, y: inout Int) {
    int tmp = x
    x = y
    y = tmp
}
var tup = (h1:2,h2:3)
swap(&tup.h1,&tup.h2)

swap函数对h1和h2有写访问,h1和h2是tup的元素,他们在同一块内存,所以会冲突

对于struct有一个特例。当满足以下三个条件时,访问struct的property不冲突:

  • 只访问存储型属性,不访问计算型属性或者类属性
  • structure 是本地变量,不是全局变量
  • structur要么不被任何闭包捕获,要么只被废逃逸闭包捕获