โพรโทคอล 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ปัญหาการแย่งข้อมูล
- โพรโทคอล Sendable
- การแยกส่วนของแอกเตอร์และ nonisolated
- การย้ายไปใช้การทำงานพร้อมกันแบบเข้มงวด