1. 程式人生 > 其它 >Swift Lazy計算屬性的執行緒安全分析

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; }