0Pricing
Swift Academy · บทเรียน

โพรโทคอล Sendable

ระบุว่าชนิดปลอดภัยต่อการข้ามขอบเขตการทำงานพร้อมกัน

โพรโทคอล Sendable เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

ความหมายของโปรโตคอลส่งต่อได้

Sendable เป็นโปรโตคอลทำเครื่องหมาย ชนิดข้อมูลที่สอดคล้องตามโปรโตคอลนี้รับประกันว่าจะ แบ่งปันข้ามขอบเขตการทำงานพร้อมกันได้อย่างปลอดภัย โดยไม่ทำให้เกิดภาวะข้อมูลแข่งกัน

โปรโตคอลนี้ไม่มีเมธอด แต่เป็นการรับประกันเกี่ยวกับความปลอดภัยของเธรดที่คอมไพเลอร์ตรวจสอบ

protocol Sendable {}

ชนิดค่าโดยมากเป็น Sendable

โครงสร้างและชนิดแจกแจงที่พร็อพเพอร์ตีที่จัดเก็บทั้งหมดเป็น Sendable สามารถสอดคล้องตามโปรโตคอลได้โดยอัตโนมัติ

เนื่องจากค่าจะถูกคัดลอกเมื่อส่งผ่าน แต่ละงานจึงได้รับสำเนาอิสระของตนเอง

struct User: Sendable {
    let id: Int
    let name: String
}

การสอดคล้องโดยนัย

ชนิดค่าอีกหลายชนิดจะได้รับ Sendable โดยนัย ได้แก่ โครงสร้างและชนิดแจกแจงแบบแช่แข็งที่ไม่เปิดเผยซึ่งมีสมาชิกเป็น Sendable ทูเพิลของชนิด Sendable และเมทาไทป์

สำหรับชนิดค่าภายใน คุณมักไม่จำเป็นต้องเขียน : Sendable เลย

enum Direction { case north, south, east, west }
// Implicitly Sendable: no associated non-Sendable data

เมื่อชนิดโครงสร้างเป็น NOT Sendable

หากโครงสร้างเก็บคุณสมบัติที่จัดเก็บซึ่งส่งต่อไม่ได้ไว้ ก็จะไม่ใช่ประเภทที่ส่งต่อได้

ในที่นี้ การอ้างอิงคลาสทำให้เข้าถึงสถานะที่เปลี่ยนแปลงร่วมกันได้ ดังนั้นคอมไพเลอร์จึงปฏิเสธการสอดคล้องโดยอัตโนมัติ

final class Box { var value = 0 }
struct Wrapper { // not Sendable
    let box: Box // class with mutable state
}

คลาสและค่าที่ส่งต่อได้

คลาสเป็นชนิดอ้างอิง ดังนั้นสำเนาจึงใช้ตัวอย่างเดียวกันร่วมกัน คลาสจะเป็นประเภทที่ส่งต่อได้ก็ต่อเมื่อเป็นคลาสสุดท้าย และคุณสมบัติที่จัดเก็บทั้งหมดไม่เปลี่ยนแปลงและส่งต่อได้

final class ImmutablePoint: Sendable {
    let x: Double
    let y: Double
    init(x: Double, y: Double) { self.x = x; self.y = y }
}

@unchecked ค่าที่ส่งต่อได้

บางครั้งคุณทราบว่าคลาสปลอดภัยต่อการทำงานพร้อมกันแบบหลายเธรด เพราะคลาสป้องกันสถานะด้วยล็อก แต่คอมไพเลอร์พิสูจน์เรื่องนี้ไม่ได้ ให้ใช้ @unchecked Sendable เพื่อยืนยันความปลอดภัยด้วยตนเอง

นี่เป็นช่องทางหลบข้อจำกัด ดังนั้นคุณต้องรับผิดชอบความถูกต้องเอง

import Foundation
final class Cache: @unchecked Sendable {
    private let lock = NSLock()
    private var storage: [String: Int] = [:]
    func set(_ k: String, _ v: Int) {
        lock.lock(); defer { lock.unlock() }
        storage[k] = v
    }
}

คลอสเชอร์ @Sendable

คลอสเชอร์สามารถกำกับด้วย @Sendable ได้เช่นกัน คลอสเชอร์เช่นนี้สามารถส่งข้ามขอบเขตการทำงานพร้อมกันได้ ดังนั้นคอมไพเลอร์จึงตรวจสอบว่าคลอสเชอร์จับเฉพาะค่าที่ส่งต่อได้เท่านั้น

func run(_ work: @Sendable () -> Void) {
    work()
}
let name = "Ada" // immutable, Sendable
run { print(name) }

การจับสถานะที่เปลี่ยนแปลงได้ถูกปฏิเสธ

คลอสเชอร์ @Sendable ไม่สามารถจับตัวแปรที่เปลี่ยนแปลงได้ เพราะงานสองงานอาจแก้ไขตัวแปรนั้นพร้อมกัน

คอมไพเลอร์จะแจ้งข้อผิดพลาดเกี่ยวกับการจับค่าด้านล่าง

var counter = 0
// Error: @Sendable closure captures mutable var
// run { counter += 1 }

ค่าที่ส่งต่อได้ในส่วนติดต่อแบบอะซิงโครนัส

จุดเริ่มต้นของการทำงานพร้อมกันต้องใช้ค่าที่ส่งต่อได้ คลอสเชอร์ของ Task เป็น @Sendable และค่าที่ส่งให้แอกเตอร์อื่นต้องเป็นค่าที่ส่งต่อได้

นี่คือวิธีที่ระบบชนิดหยุดยั้งไม่ให้ข้อมูลที่ไม่ปลอดภัยต่อการทำงานพร้อมกันหลายเธรดรั่วไหลข้ามงาน

func process(_ user: User) async {
    Task {
        // user is Sendable, safe to capture
        print(user.name)
    }
}

ข้อจำกัดค่าที่ส่งต่อได้สำหรับชนิดทั่วไป

คุณสามารถกำหนดให้ชนิดทั่วไปต้องเป็นค่าที่ส่งต่อได้ ฟังก์ชันที่สร้างงานโดยใช้อาร์กิวเมนต์ของฟังก์ชันควรจำกัดให้อาร์กิวเมนต์นั้นเป็น Sendable

func dispatch<T: Sendable>(_ value: T) {
    Task { print(value) }
}

ค่าที่ส่งต่อได้กับแอกเตอร์

Sendable ตอบคำถามว่า "ค่านี้ปลอดภัยที่จะส่งต่อหรือไม่" ส่วน actor ตอบว่า "จะปกป้องสถานะที่เปลี่ยนแปลงได้อย่างไร"

ทั้งสองทำงานร่วมกันได้ แอกเตอร์เป็นค่าที่ส่งต่อได้โดยปริยาย เพราะการเข้าถึงสถานะของแอกเตอร์ถูกจัดลำดับให้ทำทีละรายการ

actor Logger { } // actors are implicitly Sendable

ตรวจสอบความเข้าใจ: ค่าที่ส่งต่อได้

ทดสอบความเข้าใจของคุณเกี่ยวกับการสอดคล้องกับค่าที่ส่งต่อได้

สรุป: โปรโตคอลค่าที่ส่งต่อได้

Sendable ใช้ระบุว่าชนิดต่าง ๆ ปลอดภัยที่จะส่งข้ามขอบเขตการทำงานพร้อมกัน ชนิดค่าที่ไม่เปลี่ยนแปลงจะสอดคล้องโดยอัตโนมัติ คลาสสุดท้ายที่ไม่เปลี่ยนแปลงสามารถสอดคล้องได้ และคลาสที่ปลอดภัยต่อการทำงานพร้อมกันหลายเธรดให้ใช้ @unchecked Sendable

คลอสเชอร์ @Sendable จับได้เฉพาะค่าที่ส่งต่อได้ และส่วนติดต่อแบบอะซิงโครนัสต้องใช้ค่าที่ส่งต่อได้เพื่อป้องกันการใช้ข้อมูลร่วมกันอย่างไม่ปลอดภัย เมื่อทำงานร่วมกับแอกเตอร์ ค่าที่ส่งต่อได้จึงเป็นรากฐานระดับระบบชนิดสำหรับความปลอดภัยจากสภาวะแข่งขันของข้อมูลใน Swift

คำถามที่พบบ่อย

บทเรียน “โพรโทคอล Sendable” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “โพรโทคอล Sendable” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “โพรโทคอล Sendable”

ระบุว่าชนิดปลอดภัยต่อการข้ามขอบเขตการทำงานพร้อมกัน คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “โพรโทคอล Sendable” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม

ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ปัญหาการแย่งข้อมูล
  2. โพรโทคอล Sendable
  3. การแยกส่วนของแอกเตอร์และ nonisolated
  4. การย้ายไปใช้การทำงานพร้อมกันแบบเข้มงวด
← กลับไปที่ Swift Academy