- Published on
Swiftda Sendable
- Authors
- Name
- ShoxruxC
- @iOSdasturchi
Sendable β thread-safe turlar
Sendable β turni bir concurrency domain dan boshqasiga xavfsiz uzatish mumkinligini bildiruvchi protokol. Oddiy qilib aytganda: agar biror qiymatni Task { } ichiga yoki actor ga yuborayotgan bo'lsangiz β u qiymatning turi Sendable bo'lishi kerak. Swift 6 da bu qat'iy tekshiriladi β Sendable bo'lmagan turni Task yoki actor chegarasi orqali uzatish kompilyatsiya xatosi beradi.
Nima uchun kerak? β Agar ikki thread bir xil ob'ektga bir vaqtda kirsa va uni o'zgartirsa β data race paydo bo'ladi. Sendable bu muammoni oldini oladi: faqat xavfsiz turlar uzatilishi mumkin.
Sendable tushunchasi
Value type lar (Int, String, Bool, struct) avtomatik Sendable β chunki ular uzatilganda nusxa olinadi va original o'zgarmaydi. Class lar esa default Sendable emas β chunki reference type: bir nechta thread bir xil ob'ektga kirishi va o'zgartirishi mumkin.
// βββββββββββββββββββββββββββββββββββββββ
// QAYSI TURLAR SENDABLE?
// βββββββββββββββββββββββββββββββββββββββ
// β
Avtomatik Sendable β value typelar
// Int, Double, Bool, String β nusxa oladi, original o'zgarmaydi
let son: Int = 42 // β
Sendable
// β
Struct β barcha property lari Sendable bo'lsa
struct Nuqta: Sendable {
let x: Double // β
Double β Sendable
let y: Double // β
Double β Sendable
}
// β
Enum β barcha associated value lari Sendable bo'lsa
enum Natija: Sendable {
case muvaffaqiyat(String) // β
String β Sendable
case xato(Int) // β
Int β Sendable
}
// β Class β default Sendable emas
class OddiyClass {
var qiymat = 0 // var β boshqa thread o'zgartirishi mumkin
}
// OddiyClass() ni Task ga uzatish xavfli β data race!
// β
final class β let property lar bilan Sendable
final class XavfsizClass: Sendable {
let ism: String // β
let β o'zgarmaydi
let yosh: Int // β
let β o'zgarmaydi
// var qo'yib bo'lmaydi! Sendable buziladi
init(ism: String, yosh: Int) {
self.ism = ism
self.yosh = yosh
}
}
@Sendable closure
@Sendable β closure ning concurrency chegarasini xavfsiz kesib o'tishini bildiradi. Task { } ning closure si avtomatik @Sendable. Bu degani β closure ichida capture qilingan barcha qiymatlar Sendable bo'lishi kerak. var o'zgaruvchini capture qilish xavfli β let ishlatish kerak.
// βββββββββββββββββββββββββββββββββββββββ
// @SENDABLE CLOSURE
// Concurrency chegarasini kesib o'tadigan closure
// βββββββββββββββββββββββββββββββββββββββ
// Task init β @Sendable closure qabul qiladi
var tashqariQiymat = 0
Task { // @Sendable closure
// β tashqariQiymat ni o'zgartirish xavfli
// Swift 6: kompilyatsiya xatosi
// tashqariQiymat += 1
}
// β
TO'G'RI β Sendable qiymatlar bilan
let xavfsizQiymat = 42 // let β Sendable
Task {
// β
let qiymat β nusxa olinadi, xavfsiz
print(xavfsizQiymat)
}
// @Sendable funksiya parametr sifatida
func fonDaBajar(ish: @Sendable () -> Void) {
Task {
ish()
}
}
// Ishlatish
let ism = "Ali" // let β Sendable
fonDaBajar {
print("Salom, \(ism)!") // β
let capture β xavfsiz
}
@unchecked Sendable
Ba'zan class ni Sendable qilish kerak, lekin var property lar bor. Bunday hollarda @unchecked Sendable ishlatiladi β bu compiler ga "men o'zim thread-safety ni ta'minlayman" degan ma'noni beradi. Compiler tekshirmaydi β javobgarlik to'liq dasturchida. Odatda NSLock, DispatchQueue yoki boshqa sinxronizatsiya mexanizmlari bilan himoyalanadi.
// βββββββββββββββββββββββββββββββββββββββ
// @UNCHECKED SENDABLE
// "Men o'zim thread-safety ni kafolatlayaman"
// Compiler tekshirmaydi β javobgarlik sizda!
// βββββββββββββββββββββββββββββββββββββββ
final class ThreadXavfsizKesh: @unchecked Sendable {
private let lock = NSLock() // Qo'lda qulflash
private var saqlangan: [String: Any] = [:]
func saqlash(kalit: String, qiymat: Any) {
lock.lock()
defer { lock.unlock() }
saqlangan[kalit] = qiymat
}
func olish(kalit: String) -> Any? {
lock.lock()
defer { lock.unlock() }
return saqlangan[kalit]
}
}
// β
Xavfsiz β lock bilan himoyalangan
// Lekin compiler buni bilmaydi β @unchecked ishonadi
// OGOHLANTRISH: @unchecked ni faqat haqiqatan
// thread-safe qilganingizda ishlating!
// Aks holda β data race va crash
Sendable tekshiruvi amalda
Swift 6 da Sendable tekshiruvi qat'iy. Quyida non-Sendable turni Task ga uzatishning muammosi va uchta yechimi ko'rsatilgan: struct ishlatish, actor ishlatish yoki final class + let ishlatish.
// βββββββββββββββββββββββββββββββββββββββ
// SWIFT 6 DA STRICT CHECKING
// βββββββββββββββββββββββββββββββββββββββ
// β Kompilyatsiya xatosi β non-Sendable turni Task ga uzatish
class Foydalanuvchi {
var ism = "Ali" // var β xavfli
}
let user = Foydalanuvchi()
Task {
// β Swift 6: "Capture of 'user' with non-Sendable type
// 'Foydalanuvchi' in @Sendable closure"
// print(user.ism)
}
// β
Yechimlar:
// 1. struct ishlatish
struct FoydalanuvchiXavfsiz: Sendable {
let ism: String
}
// 2. actor ishlatish
actor FoydalanuvchiActor {
var ism = "Ali"
}
// 3. final class + let
final class FoydalanuvchiFinal: Sendable {
let ism: String
init(ism: String) { self.ism = ism }
}
Qoidalar jadvali
| Tur | Sendable? | Shart |
|---|---|---|
| Int, String, Bool | β Ha | Har doim |
| struct | β Ha | Barcha property Sendable |
| enum | β Ha | Barcha associated value Sendable |
| actor | β Ha | Har doim β izolyatsiya kafolat |
| final class | β οΈ Shartli | Barcha stored property let va Sendable |
| class | β Yo'q | @unchecked bilan qo'lda |
| Closure | β οΈ Shartli | @Sendable belgilanishi kerak |
π― Topshiriq
Buyurtma struct yarating (barcha property lar Sendable). BuyurtmaMenejeri actor yarating. 10 ta parallel Task dan buyurtma qo'shing. Keyin final class KeshMenejer: @unchecked Sendable yarating β NSLock bilan himoyalang. Ikkalasini solishtiring.