Share memory by communicating ในภาษา Go ทำงานอย่างไร?
มีโอกาสคุยกับ หน่อง Anuchit Prasertsang เมื่อนานมาแล้วเกี่ยวกับ Go Channel และ Share memory by communication เลยอยากจะสรุปความรู้เหล่านี้ ไว้ในบล็อกเพื่อที่มือใหม่ หรือ คนที่ใช้ภาษานี้มาสักระยะ จะได้เห็นแนวคิดพื้นฐานที่เป็นรากฐานสำคัญของแนวคิดของภาษา Go ว่า … มันสุดยอดจริงๆ
Communication by shared memory
แนวคิดของ thread programming ในหลายๆภาษา จะใช้เทคนิค Shared Memory ในการสื่อสารระหว่าง thread โดยให้แต่ละ thread สามารถเข้าถึง memory ได้โดยตรง
ข้อดี คือ CPU ที่เราถืออยู่เนี่ย เข้าถึงข้อมูล เพื่องาน อ่าน และ เขียนได้ไวมาก แต่ มันย่อมมีผลลัพธ์ตามมา คือ ใครๆก็สามารถเข้ามาอ่าน และ เขียน ตัวแปร ใน memory address นั้นๆในเวลาเดียวกันได้ สิ่งที่เกิดขึ้น ก็ คือ race condition หรือ การเกิดของข้อมูลเขียนทับกัน หรือ งานที่อ่านข้อมูลได้ข้อมูลผิดๆไป
ที่สำคัญเลยเราต้องมาจัดการเรื่อง thread-safe ทุกครั้งเมื่อมีการเข้าใช้ข้อมูลประเภท shared memory ในแต่ละ process
Go Philosophy เลยบอกเอาไว้ว่า…
Do not communicate by sharing memory; instead, share memory by communicating.
Share memory by communicating
ใน Go เราจะสร้าง ท่อในการสื่อสารระหว่าง Go Routine เรียกว่า Channel โดยที่เราให้สิทธิ์ในการเข้าถึง data นั้นๆ ให้กับ channel
ซึ่งเบื้องหลังการจัดงานพวก concurrency นั้น จะเป็น kernel ที่จัดการให้เรา โดยที่เราไม่ต้องสนใจทำพวก Mutex, Optimistic Locking หรือ แนวทางป้องกัน Race condition ต่างๆ ทั้งหมดด้วยตัวเอง
การมาของ Channel
ช่วยให้การสื่อสารระหว่าง go routine สามารถคุยกันแบบ synchronization capability ลดการขัดแย้งของ data ลงไปได้ มีคนกลางจัดการเรื่องการสื่อสารให้
มีเพียงแค่ 1 goroutine เท่านั้น ที่สามารถสื่อสารกับ channel ช่วงเวลาหนึ่ง แนวคิดนี้ จะสร้าง asynchronous parallel programs ให้เกิดขึ้นมา
ที่กล่าวมาทั้งหมด คือ การเอาแนวคิดของ Messaging Passing Method มาปรับใช้ในภาษา Go
Go uses goroutines and channels instead of threads, consuming just 2KB memory
Go นั้นออกแบบมาจาก pain ของหลายๆภาษา ซึ่งนี่ก็เป็นอีกจุดเด่นของ Go เลยที่ใช้ memory buffer น้อยมาก