Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

การประมวลผลแบบขนานอย่างไร้กังวล (Fearless Concurrency)

การจัดการการโปรแกรมแบบคอนเคอร์เรนต์ (Concurrent programming) อย่างปลอดภัยและมีประสิทธิภาพเป็นอีกหนึ่งเป้าหมายหลักของ Rust โดย การโปรแกรมแบบคอนเคอร์เรนต์ (Concurrent programming) ซึ่งเป็นแบบที่ส่วนต่างๆ ของโปรแกรมทำงานได้อย่างเป็นอิสระต่อกัน และ การโปรแกรมแบบขนาน (Parallel programming) ซึ่งเป็นแบบที่ส่วนต่างๆ ของโปรแกรมทำงานในเวลาเดียวกัน มีความสำคัญเพิ่มขึ้นเรื่อยๆ เนื่องจากคอมพิวเตอร์จำนวนมากเริ่มใช้งานหน่วยประมวลผลแบบหลายคอร์ (multiple processors) ในอดีตการโปรแกรมในบริบทเหล่านี้เป็นเรื่องยากและเกิดข้อผิดพลาดได้ง่าย แต่ Rust หวังว่าจะเปลี่ยนเรื่องนั้น

ในตอนแรก ทีมพัฒนา Rust คิดว่าการรับประกันความปลอดภัยของหน่วยความจำและการป้องกันปัญหาเรื่องคอนเคอร์เรนซี (concurrency) เป็นสองสิ่งที่ท้าทายและแยกออกจากกัน ซึ่งต้องแก้ด้วยวิธีการที่แตกต่างกัน แต่เมื่อเวลาผ่านไป ทีมพบว่าระบบความเป็นเจ้าของ (ownership) และระบบชนิดข้อมูล (type system) เป็นเครื่องมือที่ทรงพลังที่ช่วยจัดการทั้งความปลอดภัยของหน่วยความจำ และ ปัญหาเรื่องคอนเคอร์เรนซี! ด้วยการใช้ประโยชน์จากระบบความเป็นเจ้าของและการตรวจสอบชนิดข้อมูล ข้อผิดพลาดด้านคอนเคอร์เรนซีหลายอย่างใน Rust จะกลายเป็นข้อผิดพลาดในขั้นตอนคอมไพล์ (compile-time errors) แทนที่จะเป็นข้อผิดพลาดขณะโปรแกรมทำงาน (runtime errors) ดังนั้น แทนที่จะต้องเสียเวลามากมายในการพยายามจำลองสถานการณ์เป๊ะๆ ที่ทำให้เกิดบั๊กคอนเคอร์เรนซีในขณะโปรแกรมทำงาน โค้ดที่ไม่ถูกต้องจะถูกปฏิเสธไม่ให้คอมไพล์พร้อมแสดงข้อผิดพลาดที่อธิบายปัญหานั้น ส่งผลให้คุณสามารถแก้ไขโค้ดขณะที่กำลังพัฒนาอยู่ได้ แทนที่จะต้องไปแก้หลังจากปล่อยโปรแกรมไปยังสภาพแวดล้อมจริง (production) เราตั้งชื่อเล่นให้กับแง่มุมนี้ของ Rust ว่า การประมวลผลแบบขนานอย่างไร้กังวล (Fearless concurrency) ซึ่งช่วยให้คุณสามารถเขียนโค้ดที่ปราศจากบั๊กแอบแฝงที่ซับซ้อน และรีแฟกเตอร์ (refactor) ได้ง่ายโดยไม่ก่อให้เกิดบั๊กใหม่ขึ้นมา

หมายเหตุ: เพื่อความเรียบง่าย เราจะอ้างถึงปัญหาหลายๆ อย่างว่า คอนเคอร์เรนต์ (concurrent) แทนที่จะระบุเจาะจงว่า คอนเคอร์เรนต์ และ/หรือ ขนาน (concurrent and/or parallel) สำหรับในบทนี้ โปรดทำความเข้าใจในใจว่าหมายถึง คอนเคอร์เรนต์ และ/หรือ ขนาน ทุกครั้งที่เราใช้คำว่า คอนเคอร์เรนต์ ส่วนในบทถัดไป ซึ่งข้อแตกต่างระหว่างสองคำนี้มีความสำคัญมากกว่า เราจะระบุอย่างละเอียดมากขึ้น

หลายภาษาเขียนโปรแกรมมีแนวทางที่ตายตัวเกี่ยวกับการแก้ไขปัญหาด้านคอนเคอร์เรนซี เช่น ภาษา Erlang มีฟังก์ชันการทำงานที่งดงามสำหรับคอนเคอร์เรนซีแบบส่งข้อความ (message-passing concurrency) แต่มีวิธีที่ไม่ชัดเจนสำหรับการแบ่งปันสถานะ (share state) ระหว่างเธรด การสนับสนุนเพียงแค่ชุดย่อยของการแก้ปัญหาที่เป็นไปได้ถือเป็นกลยุทธ์ที่สมเหตุสมผลสำหรับภาษาระดับสูง (higher-level languages) เนื่องจากภาษาระดับสูงสัญญาว่าได้รับประโยชน์จากการสละการควบคุมบางส่วนเพื่อแลกกับนามธรรม (abstractions) อย่างไรก็ตาม ภาษาระดับล่าง (lower-level languages) คาดหวังว่าจะมอบทางออกที่มีประสิทธิภาพดีที่สุดในทุกสถานการณ์และมีนามธรรมครอบทับฮาร์ดแวร์น้อยกว่า ดังนั้น Rust จึงมอบเครื่องมือที่หลากหลายสำหรับการจำลองปัญหาในรูปแบบใดก็ตามที่เหมาะสมกับสถานการณ์และความต้องการของคุณ

นี่คือหัวข้อที่เราจะครอบคลุมในบทนี้:

  • วิธีการสร้างเธรด (threads) เพื่อรันโค้ดหลายส่วนในเวลาเดียวกัน
  • คอนเคอร์เรนซีแบบ ส่งข้อความ (Message-passing) ซึ่งมีช่องทาง (channels) คอยส่งข้อความระหว่างเธรด
  • คอนเคอร์เรนซีแบบ แบ่งปันสถานะ (Shared-state) ซึ่งเธรดหลายเธรดสามารถเข้าถึงข้อมูลชิ้นเดียวกันได้
  • เทรต Sync และ Send ซึ่งขยายขอบเขตการรับประกันคอนเคอร์เรนซีของ Rust ไปยังชนิดข้อมูลที่ผู้ใช้กำหนดเอง ตลอดจนชนิดข้อมูลที่ไลบรารีมาตรฐานจัดหาไว้ให้