ios - सिंगलटन में गेटर और सेटर के लिए थ्रेड सुरक्षा




swift swift3 (2)

आप सही हैं कि आपके द्वारा लिखी गई वे गलती सुरक्षित नहीं हैं। स्विफ्ट में, सबसे आसान (सबसे सुरक्षित पढ़ें) इस समय इसे प्राप्त करने के लिए लॉकिंग तंत्र के रूप में ग्रांड सेंट्रल डिस्पैच कतार का उपयोग कर रहा है यह सरलतम (और इसके बारे में सबसे आसान कारण) इसे प्राप्त करने के लिए एक बुनियादी सीरियल कतार के साथ है

class MySingleton {

    static let shared = MySingleton()

    // Serial dispatch queue
    private let lockQueue = DispatchQueue(label: "MySingleton.lockQueue")

    private var _myName: String
    var myName: String {
        get {
            var result: String!

            lockQueue.sync {
                result = self._myName
            }

            return result
        }

        set {
            lockQueue.sync {
                self._myName = newValue
            }
        }
    }

    private init() {
        _myName = "initial name"
    }
}

सीरियल डिस्पैच कतार का उपयोग पहले में, पहले निष्पादन के साथ ही डेटा पर "लॉक" प्राप्त करने की गारंटी देगा। यही है, डेटा को पढ़ा नहीं जा सकता जब इसे बदला जा रहा है। इस दृष्टिकोण में, हम sync को वास्तविक रीड और निष्पादित करने के लिए डेटा का उपयोग करते हैं, जिसका मतलब है कि कॉलर को हमेशा उसकी लॉन्चिंग की प्रतीक्षा करने के लिए मजबूर किया जाएगा, अन्य लॉकिंग प्रिमिटीव के समान।

नोट: यह सबसे अधिक प्रदर्शनकारी दृष्टिकोण नहीं है, लेकिन यह पढ़ना और समझना सरल है। यह दौड़ की परिस्थितियों से बचने के लिए एक सामान्य सामान्य उद्देश्य समाधान है लेकिन समानांतर एल्गोरिथम विकास के लिए सिंक्रनाइज़ेशन प्रदान करने के लिए नहीं है।

सूत्रों का कहना है: https://mikeash.com/pyblog/friday-qa-2015-02-06-locks-thread-safety-and-swift.html उद्देश्य-सी के "सिंक्रनाइज़" के समान स्विफ्ट क्या है?

मैंने स्विफ्ट 3 में एक सरल सिंगलटन बनाया है:

class MySingleton {
    private var myName: String
    private init() {}
    static let shared = MySingleton()

    func setName(_ name: String) {
        myName = name
    }

    func getName() -> String {
        return myName
    }
}

चूंकि मैंने init() निजी बना दिया है, और shared आवृत्ति को static let से घोषित shared , मुझे लगता है कि प्रारंभकर्ता थ्रेड सुरक्षित है I लेकिन मेरे नाम के लिए प्राप्तकर्ता और सेटर फ़ंक्शन के बारे में क्या, क्या वे सुरक्षित हैं?


यह करने के लिए एक अलग तरीके (और यह एक Xcode 9 खेल का मैदान से है) एक सीरियल कतार के बजाय एक समवर्ती कतार का उपयोग करना है

final class MySingleton {
    static let shared = MySingleton()

    private let nameQueue = DispatchQueue(label: "name.accessor", qos: .default, attributes: .concurrent)
    private var _name = "Initial name"

    private init() {}

    var name: String {
        get {
            var name = ""
            nameQueue.sync {
                name = _name
            }

            return name
        }
        set {
            nameQueue.async(flags: .barrier) {
                self._name = newValue
            }
        }
    }
}
  • एक समवर्ती कतार का उपयोग करने का मतलब है कि कई थ्रेड से पढ़ता है एक दूसरे को अवरुद्ध नहीं कर रहा है चूंकि कोई बदलाव नहीं हो रहा है, मान को एक साथ पढ़ा जा सकता है, क्योंकि ...
  • हम। .barrier async प्रेषण का उपयोग करते हुए नए मान सेट कर रहे हैं। ब्लॉक को अतुल्यकालिक रूप से निष्पादित किया जा सकता है क्योंकि कॉलर को मान सेट होने की प्रतीक्षा करने की कोई आवश्यकता नहीं है। इस ब्लॉक को तब तक नहीं चलाया जाएगा जब तक सभी अन्य ब्लॉकों को इसके समवर्ती कतार में पूरा नहीं किया जाएगा। इसलिए, मौजूदा लंबित पढ़ना प्रभावित नहीं होगा, जबकि इस सेटर को चलाने की प्रतीक्षा है। बाधा का अर्थ है कि जब वह चलने लगेंगे, तो कोई अन्य ब्लॉक नहीं चलेंगे। प्रभावी रूप से, सेटर की अवधि के लिए सीरियल कतार में कतार को बदलना। आगे नहीं पढ़ा जा सकता है जब तक कि यह ब्लॉक पूर्ण न हो। जब ब्लॉक पूरा हो चुका है तो नया मान सेट कर दिया गया है, इस सेटर के बाद जोड़ा जाने वाला कोई भी एयरटर अब समवर्ती रूप से चला सकता है।






swift3