同時讀寫一個存儲地址舷礼,會引發(fā)訪問沖突芥颈。
重疊訪問主要出現(xiàn)在:
- 使用in-out參數(shù)的函數(shù)和方法
- 結構體的mutating方法里
in-out參數(shù)的訪問沖突
- 變量傳入inout參數(shù)的方法之后,調用方法的同時又訪問了傳入的變量
var stepSize = 1
func increment(_ number: inout Int) {
number += stepSize
}
func test() {
// 復制一份
// 否則報錯:Simultaneous accesses to 0x7fda39420ca0, but modification requires exclusive access.
var copyStepSize = stepSize
increment(©StepSize)
}
- 同一個變量傳入了含有多個inout參數(shù)的方法里潜慎,造成同時訪問的情況
func balance(_ x: inout Int, _ y: inout Int) {
let sum = x + y
x = sum / 2
y = sum - x
}
func test() {
var playerOneScore = 42
var playerTwoScore = 30
balance(&playerOneScore, &playerTwoScore) // 正常
// copy之后
var copyPlayerOneScore = playerOneScore
var copyPlayerTwoScore = playerOneScore
balance(©PlayerOneScore, ©PlayerTwoScore)
print(copyPlayerOneScore)
// 錯誤:playerOneScore 訪問沖突
}
- 結構體的mutating方法
對self的寫操作會從mutating方法的開始到結束缆巧。
mutating 方法在調用期間需要對 self 發(fā)起寫訪問,而同時 in-out 參數(shù)也需要寫訪問余境。
屬性的訪問沖突
任何情況下驻呐,對于元組元素的寫訪問都需要對整個元組發(fā)起寫訪問灌诅。這意味著對于 playerInfomation 發(fā)起的兩個寫訪問重疊了,造成沖突含末。
使用inout參數(shù)同時傳入元組的2個元素的話猜拾,就會同時訪問元組引起沖突。
限制結構體屬性的重疊訪問對于內存安全并不總是必要的佣盒。內存安全是必要的挎袜,但訪問獨占權的要求比內存安全還要更嚴格 —— 意味著即使有些代碼違反了訪問獨占權的原則,也是內存安全的。如果編譯器可以保證這種非專屬的訪問是安全的盯仪,那 Swift 就會允許這種內存安全的行為紊搪。特別是當你遵循下面的原則時,它可以保證結構體屬性的重疊訪問是安全的:
- 你訪問的是實例的存儲屬性全景,而不是計算屬性或類的屬性
- 結構體是本地變量的值耀石,而非全局變量
- 結構體要么沒有被閉包捕獲,要么只被非逃逸閉包捕獲了
如果編譯器無法保證訪問的安全性爸黄,它就不會允許訪問滞伟。