การแยกส่วนของแอกเตอร์และ nonisolated
ให้เหตุผลเกี่ยวกับขอบเขตการแยกส่วน
การแยกส่วนของแอกเตอร์และ nonisolated เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน
การแยกการเข้าถึงของแอกเตอร์คืออะไร
การแยกการเข้าถึงของแอกเตอร์ หมายความว่าสถานะที่เปลี่ยนแปลงได้ของแอกเตอร์จะถูกแตะต้องได้เฉพาะโค้ดที่ทำงานอยู่บนแอกเตอร์นั้น
รันไทม์จะจัดลำดับการเข้าถึง ดังนั้นงานสองงานจะไม่แก้ไขสถานะพร้อมกัน ซึ่งช่วยกำจัดสภาวะแข่งขันของข้อมูล
actor Counter {
private var value = 0
func increment() { value += 1 }
}การเรียกใช้แอกเตอร์
จากภายนอกแอกเตอร์ การเข้าถึงสมาชิกที่ถูกแยกการเข้าถึงจะเป็นแบบ อะซิงโครนัส คุณต้องใช้ await เพราะการเรียกอาจหยุดรอจนกว่าแอกเตอร์จะว่าง
let counter = Counter()
func useCounter() async {
await counter.increment()
}ภายในแอกเตอร์: แบบซิงโครนัส
ภายในเมธอดของแอกเตอร์เอง คุณอยู่ในขอบเขตที่แยกการเข้าถึงอยู่แล้ว จึงเข้าถึงสถานะแบบซิงโครนัสได้ โดยไม่ต้องใช้ await กับ self
actor Counter {
private var value = 0
func incrementTwice() {
value += 1 // synchronous: already isolated
value += 1
}
}สมาชิกที่ไม่แยกการเข้าถึง
กำกับสมาชิกด้วย nonisolated เมื่อสมาชิกนั้นไม่แตะต้องสถานะที่เปลี่ยนแปลงได้ สมาชิกดังกล่าวทำงานแบบซิงโครนัสจากที่ใดก็ได้ โดยไม่ต้องใช้ await
วิธีนี้เหมาะอย่างยิ่งสำหรับค่าที่คำนวณจากข้อมูลที่ไม่เปลี่ยนแปลงเท่านั้น
actor User {
let id: Int
var sessionCount = 0
init(id: Int) { self.id = id }
nonisolated var label: String { "User #\(id)" }
}เหตุใดการไม่แยกการเข้าถึงจึงปลอดภัย
สมาชิก nonisolated สามารถอ่านได้เฉพาะสถานะที่ ไม่เปลี่ยนแปลง (let) หรือสถานะที่ส่งต่อได้ในลักษณะอื่นเท่านั้น
คอมไพเลอร์จะปฏิเสธความพยายามใด ๆ ที่เข้าถึงสถานะซึ่งแยกการเข้าถึงและเปลี่ยนแปลงได้จากบริบทที่ไม่แยกการเข้าถึง
actor User {
let id: Int
var sessionCount = 0
init(id: Int) { self.id = id }
// Error: cannot read mutable sessionCount here
// nonisolated var bad: Int { sessionCount }
}การไม่แยกการเข้าถึงกับโปรโตคอล
nonisolated เป็นสิ่งจำเป็นเมื่อแอกเตอร์สอดคล้องกับโปรโตคอลแบบซิงโครนัส เมธอดของโปรโตคอลไม่สามารถเป็นแบบอะซิงโครนัสได้ ดังนั้นจึงต้องหลีกเลี่ยงสถานะที่ถูกแยกการเข้าถึง
actor Item: CustomStringConvertible {
let name: String
init(name: String) { self.name = name }
nonisolated var description: String { "Item: \(name)" }
}MainActor
@MainActor คือแอกเตอร์ส่วนกลางที่แยกโค้ดให้ทำงานบนเธรดหลัก การอัปเดตส่วนติดต่อผู้ใช้ควรอยู่ที่นี่
ใส่แอตทริบิวต์กำกับชนิด เมธอด หรือคุณสมบัติ เพื่อผูกสิ่งเหล่านั้นไว้กับแอกเตอร์หลัก
@MainActor
final class ViewModel {
var title = "Hello"
func refresh() { title = "Updated" }
}การย้ายข้ามแอกเตอร์
เมื่อคุณเรียกจากแอกเตอร์หนึ่งไปยังอีกแอกเตอร์หนึ่ง รันไทม์จะ ย้าย ไปยังตัวประมวลผลอื่นและหยุดรอ การหยุดรอนั้นเองคือจุดที่ await ปรากฏขึ้น
actor Database { func load() -> Int { 42 } }
@MainActor
func show(_ db: Database) async {
let v = await db.load() // hop to db actor
print(v) // hop back to main
}การกลับเข้าใหม่ของแอกเตอร์
แอกเตอร์สามารถ กลับเข้าใหม่ได้ เมื่อเมธอดหยุดรอด้วย await แอกเตอร์อาจทำงานอื่นที่อยู่ในคิวก่อนที่การทำงานหลัง await จะดำเนินต่อ
สถานะที่คุณอ่านก่อน await อาจเปลี่ยนไปแล้วหลังจากนั้น ให้ตรวจสอบสมมติฐานอีกครั้งหลังจุดหยุดรอ
actor Store {
var ready = false
func prepare() async {
ready = false
await Task.yield() // other calls may run here
ready = true
}
}พารามิเตอร์แบบแยกการเข้าถึง
ฟังก์ชันสามารถรับพารามิเตอร์แอกเตอร์แบบ isolated และให้เนื้อความของฟังก์ชันทำงานบนแอกเตอร์นั้นได้ โดยไม่ต้องเป็นสมาชิกของแอกเตอร์
func bump(on counter: isolated Counter) {
// runs isolated to counter; synchronous access
}แอกเตอร์ส่วนกลางสำหรับระบบย่อย
คุณสามารถกำหนดแอกเตอร์ส่วนกลางของคุณเองเพื่อแยกระบบย่อยทั้งหมด เช่น กระบวนการเรนเดอร์ ให้ทำงานบนตัวประมวลผลเดียว
@globalActor
actor RenderActor {
static let shared = RenderActor()
}
@RenderActor func draw() { }ตรวจสอบความเข้าใจ: การแยกการเข้าถึง
ทดสอบความเข้าใจของคุณเกี่ยวกับการแยกการเข้าถึงของแอกเตอร์
สรุป: การแยกการเข้าถึงของแอกเตอร์และการไม่แยกการเข้าถึง
การแยกการเข้าถึงของแอกเตอร์จัดลำดับการเข้าถึงสถานะที่เปลี่ยนแปลงได้ การเรียกข้ามแอกเตอร์เป็นแบบอะซิงโครนัสและต้องใช้ await สมาชิก nonisolated เลือกไม่ใช้การแยกการเข้าถึง แต่สามารถอ่านได้เฉพาะสถานะที่ไม่เปลี่ยนแปลงหรือส่งต่อได้เท่านั้น ซึ่งเป็นสิ่งสำคัญต่อการสอดคล้องกับโปรโตคอลแบบซิงโครนัส
@MainActor ผูกโค้ดไว้กับเธรดหลัก แอกเตอร์สามารถกลับเข้าใหม่ได้ สถานะจึงเปลี่ยนแปลงขณะข้าม await และแอกเตอร์ส่วนกลางสามารถแยกระบบย่อยทั้งหมดได้ การเข้าใจกฎเหล่านี้อย่างถ่องแท้คือหัวใจของการทำงานพร้อมกันอย่างปลอดภัย
คำถามที่พบบ่อย
บทเรียน “การแยกส่วนของแอกเตอร์และ nonisolated” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การแยกส่วนของแอกเตอร์และ nonisolated” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การแยกส่วนของแอกเตอร์และ nonisolated”
ให้เหตุผลเกี่ยวกับขอบเขตการแยกส่วน คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การแยกส่วนของแอกเตอร์และ nonisolated” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม
ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- ปัญหาการแย่งข้อมูล
- โพรโทคอล Sendable
- การแยกส่วนของแอกเตอร์และ nonisolated
- การย้ายไปใช้การทำงานพร้อมกันแบบเข้มงวด