Swift Lazy計算屬性的線程安全分析

一、代碼示例

//
//  ViewController.swift
//  LazyTest
//
//  Created by lilun.ios on 2021/7/30.
//

import UIKit

class ViewController: UIViewController {
    
    lazy var profileImageView: UIImageView = {

        let imageView = UIImageView(image: #imageLiteral(resourceName: "page1"))
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .scaleAspectFit
        return imageView

    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.view.addSubview(self.profileImageView)
    }


}
profileImageView 變量是不是線程安全的呢?

二、代碼分析

lazy修飾的變量是在第一次訪問的時候初始化的,如果多線程訪問這個Lazy變量,將會導致不可預知的結果
有可能不同線程生成不同的lazy變量
有可能一個線程初始化還沒完成,另外一個線程就返回了這個變量
反彙編這個變量getter的實現,判斷這個變量是不是爲空沒有加鎖,因此多線程訪問下可能出現問題
int _$s8LazyTest14ViewControllerC012profileImageC0So07UIImageC0Cvg() {
    var_58 = r13;
    memset(&var_8, 0x0, 0x8);
    memset(&var_28, 0x0, 0x8);
    memset(&var_48, 0x0, 0x8);
    swift_beginAccess(var_58 + *direct field offset for LazyTest.ViewController.($__lazy_storage_$_profileImageView in _45D895C0736D9EBC78CE118C3607CFFF) : __C.UIImageView?, &var_20, 0x20, 0x0);
    rsi = *(var_58 + rdx);
    var_78 = rsi;
    [rsi retain];
    swift_endAccess(&var_20);
    if (var_78 != 0x0) {
            var_90 = var_78;
    }
    else {
            rax = closure #1 ();
            var_98 = rax;
            [rax retain];
            swift_beginAccess(var_58 + *direct field offset for LazyTest.ViewController.($__lazy_storage_$_profileImageView in _45D895C0736D9EBC78CE118C3607CFFF) : __C.UIImageView?, &var_40, 0x21, 0x0, &var_40);
            rdx = *(var_58 + rsi);
            *(var_58 + rsi) = var_98;
            [rdx release];
            swift_endAccess(&var_40);
            var_90 = var_98;
    }
    rax = var_90;
    return rax;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章