ใช้โครงสร้างข้อมูลถาวรในภาษาที่ไม่สามารถใช้งานได้


17

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

แต่ในบางครั้งเราจะเห็นไลบรารีของโครงสร้างข้อมูลถาวรสำหรับภาษา (ตามรัฐ, OOP) เช่น Java การอ้างสิทธิ์ที่มักได้ยินในความโปรดปรานของโครงสร้างข้อมูลแบบถาวรคือเนื่องจากพวกมันไม่เปลี่ยนรูปพวกมันจึงปลอดภัยต่อเธรด

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

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

ทำไมจึงเป็นไปไม่ได้ที่ PDSs จะกลายเป็นสิ่งที่มีประโยชน์ต่อ "ความปลอดภัยของเธรด" หรือไม่? มีตัวอย่างจริงที่ PDS ช่วยในการซิงโครไนซ์หรือแก้ไขปัญหาการทำงานพร้อมกันหรือไม่? หรือ PDS เป็นเพียงวิธีหนึ่งในการจัดหาอินเตอร์เฟสแบบไร้รัฐให้กับวัตถุเพื่อสนับสนุนสไตล์การเขียนโปรแกรมที่ใช้งานได้หรือไม่


3
คุณพูดว่า "ขัดขืน" คุณหมายถึง "ถาวร" ใน "สามารถอยู่รอดการรีสตาร์ทโปรแกรม" หรือ "ไม่เปลี่ยนรูป" เช่นเดียวกับใน "ไม่มีการเปลี่ยนแปลงหลังจากการสร้าง"?
Kilian Foth

17
@KilianFoth โครงสร้างข้อมูลถาวรมีคำจำกัดความที่ดี : "โครงสร้างข้อมูลถาวรเป็นโครงสร้างข้อมูลที่มักจะรักษาเวอร์ชันก่อนหน้าของตัวมันเองเมื่อมีการแก้ไข" ดังนั้นจึงเป็นเรื่องเกี่ยวกับการใช้โครงสร้างก่อนหน้านี้อีกครั้งเมื่อโครงสร้างใหม่ที่สร้างขึ้นแทนที่จะสร้างความคงทนเช่นเดียวกับ "สามารถอยู่รอดการรีสตาร์ทโปรแกรม"
Michał Kosmulski

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

ความผิดพลาดของฉัน. ฉันไม่ทราบว่า "โครงสร้างข้อมูลถาวร" เป็นศัพท์ทางเทคนิคที่แตกต่างจากการคงอยู่เพียงอย่างเดียว
Kilian Foth

@delnan ใช่ถูกต้อง
เรย์โททอล

คำตอบ:


15

โครงสร้างข้อมูลแบบต่อเนื่อง / ไม่เปลี่ยนรูปไม่ได้แก้ปัญหาการทำงานพร้อมกันด้วยตัวเอง แต่พวกเขาทำให้การแก้ไขง่ายขึ้นมาก

พิจารณาเธรด T1 ที่ส่งชุด S ไปยังเธรด T2 อื่น หาก S ไม่สามารถเปลี่ยนแปลงได้ T1 มีปัญหา: สูญเสียการควบคุมสิ่งที่เกิดขึ้นกับ S Thread T2 สามารถแก้ไขได้ดังนั้น T1 ไม่สามารถพึ่งพาเนื้อหาของ S ได้ทั้งหมดและในทางกลับกัน - T2 ไม่สามารถมั่นใจได้ว่า T1 ไม่แก้ไข S ในขณะที่ T2 ทำงานอยู่

ทางออกหนึ่งคือการเพิ่มสัญญาประเภทหนึ่งลงในการสื่อสารของ T1 และ T2 เพื่อให้เธรดเดียวเท่านั้นที่ได้รับอนุญาตให้แก้ไข S นี่เป็นข้อผิดพลาดที่เกิดขึ้นได้ง่ายและเป็นภาระทั้งการออกแบบและการนำไปใช้

อีกวิธีหนึ่งคือ T1 หรือ T2 โคลนโครงสร้างข้อมูล (หรือทั้งสองอย่างหากไม่ได้ประสานงานกัน) แต่ถ้า S เป็นไม่ถาวรนี้เป็นราคาแพงO (n)การดำเนินงาน

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

ดูเพิ่มเติม: ถาวรเทียบกับโครงสร้างข้อมูลไม่เปลี่ยนรูป


2
อาว่า "ความปลอดภัยหัวข้อ" ในบริบทนี้เพียงหมายความว่าด้ายไม่ต้องกังวลเกี่ยวกับหัวข้ออื่น ๆ ทำลายข้อมูลที่พวกเขาเห็น แต่มีอะไรจะทำอย่างไรกับการประสานและการจัดการกับข้อมูลที่เราต้องการที่จะใช้ร่วมกันระหว่างหัวข้อ มันสอดคล้องกับสิ่งที่ฉันคิด แต่ +1 สำหรับการระบุอย่างสง่างาม "ไม่แก้ปัญหาที่เกิดขึ้นด้วยตนเอง"
Ray Toal

2
@RayToal ใช่ในบริบทนี้ "thread ปลอดภัย" หมายถึงว่า วิธีการแบ่งปันข้อมูลระหว่างเธรดเป็นปัญหาที่แตกต่างกันซึ่งมีวิธีแก้ไขปัญหามากมายตามที่คุณได้กล่าวถึง ความปลอดภัยของเธรดช่วยให้มั่นใจว่าคุณไม่ต้องกังวลว่าจะเกิดอะไรขึ้นกับข้อมูลหลังจากการแชร์ นี่เป็นเรื่องใหญ่จริง ๆ เพราะเธรดไม่จำเป็นต้องซิงโครไนซ์ว่าใครทำงานกับโครงสร้างข้อมูลและเมื่อใด
Petr Pudlák

@RayToal นี้ช่วยให้รูปแบบการทำงานพร้อมกันที่สง่างามเช่นนักแสดงซึ่งนักพัฒนาสำรองต้องจัดการกับการล็อคและการจัดการเธรดอย่างชัดเจนและขึ้นอยู่กับความไม่สามารถเปลี่ยนแปลงได้ของข้อความ - คุณไม่รู้ว่าเมื่อใดที่มีการส่งและประมวลผลข้อความ นักแสดงที่ส่งต่อไปให้
Petr Pudlák

ขอบคุณ Petr ฉันจะให้นักแสดงอีกคนดู ฉันคุ้นเคยกับกลไก Clojure ทั้งหมดและทราบว่า Rich Hickey เลือกที่จะไม่ใช้โมเดลนักแสดงอย่างน้อยก็เป็นแบบอย่างใน Erlang ยังยิ่งคุณรู้จักมากขึ้น
Ray Toal

@RayToal ลิงค์ที่น่าสนใจขอบคุณ ฉันใช้ตัวอย่างนักแสดงเท่านั้นไม่ใช่ว่าฉันกำลังบอกว่ามันจะเป็นทางออกที่ดีที่สุด ฉันไม่ได้ใช้ Clojure แต่ดูเหมือนว่าโซลูชันที่ต้องการคือ STM ซึ่งฉันชอบนักแสดงมากกว่า STM ยังต้องอาศัยความคงอยู่ / ความไม่สามารถเปลี่ยนแปลงได้ - มันเป็นไปไม่ได้ที่จะรีสตาร์ททรานแซกชันถ้ามันแก้ไขโครงสร้างข้อมูลโดยไม่สามารถเพิกถอนได้
Petr Pudlák

5

ทำไมจึงเป็นไปไม่ได้ที่ PDSs จะกลายเป็นสิ่งที่มีประโยชน์ต่อ "ความปลอดภัยของเธรด" หรือไม่? มีตัวอย่างจริงที่ PDS ช่วยในการซิงโครไนซ์หรือแก้ไขปัญหาการทำงานพร้อมกันหรือไม่?

ประโยชน์หลักของ PDS ในกรณีนี้คือคุณสามารถปรับเปลี่ยนส่วนของข้อมูลโดยไม่ทำให้ทุกอย่างไม่ซ้ำกัน (โดยไม่ต้องคัดลอกทุกอย่างเพื่อพูด) ที่มีประโยชน์มากมายที่อาจเกิดขึ้นนอกเหนือจากการอนุญาตให้คุณเขียนฟังก์ชั่นราคาถูกซึ่งปราศจากผลข้างเคียงเช่นการคัดลอกและวางข้อมูลระบบการเลิกทำเรื่องไม่สำคัญการเล่นซ้ำในเกมการแก้ไขแบบไม่ทำลาย


2

หนึ่งสามารถจินตนาการโครงสร้างข้อมูลซึ่งจะคงอยู่ แต่ไม่แน่นอน ตัวอย่างเช่นคุณสามารถใช้รายการที่เชื่อมโยงซึ่งแสดงโดยตัวชี้ไปยังโหนดแรกและการดำเนินการล่วงหน้าซึ่งจะส่งคืนรายการใหม่ประกอบด้วยโหนดหัวใหม่บวกกับรายการก่อนหน้า เนื่องจากคุณยังคงมีการอ้างอิงถึงส่วนหัวก่อนหน้าคุณสามารถเข้าถึงและแก้ไขรายการนี้ซึ่งในขณะเดียวกันก็ฝังอยู่ในรายการใหม่ ในขณะที่เป็นไปได้กระบวนทัศน์ดังกล่าวไม่ได้นำเสนอประโยชน์ของโครงสร้างข้อมูลแบบถาวรและไม่เปลี่ยนรูปเช่นมันจะไม่ปลอดภัยโดยค่าเริ่มต้น อย่างไรก็ตามอาจมีการใช้งานได้ตราบใดที่นักพัฒนาทราบว่ากำลังทำอะไรอยู่เช่นเพื่อประสิทธิภาพของพื้นที่ นอกจากนี้โปรดทราบว่าในขณะที่โครงสร้างอาจไม่แน่นอนในระดับภาษาซึ่งไม่มีสิ่งใดป้องกันรหัสจากการแก้ไข

เรื่องสั้นที่ยาวนานไม่มีการเปลี่ยนแปลงไม่ได้ (บังคับโดยภาษาหรือตามแบบแผน) โครงสร้างข้อมูลที่คงอยู่จะสูญเสียผลประโยชน์บางส่วน (ความปลอดภัยของเธรด) แต่ไม่ใช่สิ่งอื่น (ประสิทธิภาพของพื้นที่สำหรับบางสถานการณ์)

สำหรับตัวอย่างจากภาษาที่ไม่สามารถใช้งานได้ Java String.substring()จะใช้สิ่งที่ฉันเรียกว่าโครงสร้างข้อมูลถาวร สตริงถูกแสดงโดยอาร์เรย์ของอักขระรวมถึงการเริ่มต้นและสิ้นสุดการชดเชยช่วงของอาร์เรย์ที่ใช้งานจริง เมื่อสร้างสตริงย่อยวัตถุใหม่จะใช้อาร์เรย์อักขระเดิมอีกครั้งเฉพาะเมื่อมีการเริ่มต้นและสิ้นสุดการปรับชดเชย เนื่องจากStringไม่มีการเปลี่ยนแปลงมันเป็น (เกี่ยวกับการsubstring()ดำเนินการไม่อื่น) โครงสร้างข้อมูลถาวรไม่เปลี่ยนรูป

ความไม่สามารถเปลี่ยนแปลงได้ของโครงสร้างข้อมูลเป็นส่วนที่เกี่ยวข้องกับความปลอดภัยของเธรด การคงอยู่ (ใช้ชิ้นส่วนที่มีอยู่เมื่อสร้างโครงสร้างใหม่) เกี่ยวข้องกับประสิทธิภาพเมื่อทำงานกับคอลเลกชันดังกล่าว เนื่องจากสิ่งเหล่านี้ไม่สามารถเปลี่ยนแปลงได้การดำเนินการเช่นการเพิ่มรายการจึงไม่ได้แก้ไขโครงสร้างที่มีอยู่ แต่จะส่งกลับโครงสร้างใหม่โดยมีองค์ประกอบเพิ่มเติมต่อท้าย หากแต่ละครั้งที่โครงสร้างทั้งหมดถูกคัดลอกเริ่มต้นด้วยการรวบรวมที่ว่างเปล่าและเพิ่ม 1,000 องค์ประกอบทีละหนึ่งเพื่อที่จะจบลงด้วยคอลเลกชัน 1000 องค์ประกอบจะสร้างวัตถุชั่วคราวด้วย 0 + 1 + 2 + ... + 999 = มีองค์ประกอบทั้งหมด 500,000 รายการซึ่งจะเป็นการสูญเสียครั้งใหญ่ ด้วยโครงสร้างข้อมูลถาวรนี้สามารถหลีกเลี่ยงได้เนื่องจากคอลเลกชัน 1 องค์ประกอบถูกนำมาใช้ใหม่ใน 2 องค์ประกอบหนึ่งซึ่งถูกนำมาใช้ใหม่ในองค์ประกอบ 3 องค์ประกอบหนึ่งและอื่น ๆ


บางครั้งมันก็มีประโยชน์ที่จะมีวัตถุที่ไม่เปลี่ยนรูปแบบเสมือนซึ่งทุกแง่มุมของรัฐเป็นสิ่งที่เปลี่ยนแปลงไม่ได้: ความสามารถในการสร้างวัตถุที่รัฐเกือบจะเหมือนวัตถุที่กำหนด ตัวอย่างเช่นการAppendOnlyList<T>สำรองข้อมูลโดย power-of-two อาเรย์ที่เพิ่มขึ้นสามารถสร้างสแน๊ปช็อตที่ไม่เปลี่ยนรูปได้โดยไม่ต้องคัดลอกข้อมูลใด ๆ สำหรับสแนปชอตแต่ละอัน แต่อย่างใดอย่างหนึ่งไม่สามารถสร้างรายการที่มีเนื้อหาของสแน็ปช็อต ทุกอย่างเป็นอาร์เรย์ใหม่
supercat

0

ฉันลำเอียงยอมรับว่าเป็นหนึ่งในการใช้แนวคิดดังกล่าวใน C ++ โดยภาษาและลักษณะของมันเช่นเดียวกับโดเมนของฉันและแม้กระทั่งวิธีที่เราใช้ภาษา แต่เมื่อได้รับสิ่งเหล่านี้ฉันคิดว่าการออกแบบที่ไม่เปลี่ยนรูปแบบเป็นสิ่งที่น่าสนใจน้อยที่สุดเมื่อพูดถึงการได้รับผลประโยชน์จำนวนมากที่เกี่ยวข้องกับการเขียนโปรแกรมการทำงานเช่นความปลอดภัยของเธรดความง่ายในการให้เหตุผลเกี่ยวกับระบบ รวมพวกเขาในลำดับใด ๆ โดยไม่ต้องประหลาดใจอันไม่พึงประสงค์) ฯลฯ

ใช้ตัวอย่าง C ++ แบบง่าย ๆ (ไม่เหมาะสำหรับความเรียบง่ายเพื่อหลีกเลี่ยงความอับอายต่อหน้าผู้เชี่ยวชาญด้านการประมวลผลภาพ):

// Inputs an image and outputs a new one with the specified size.
Image resized_image(const Image& src, int new_w, int new_h)
{
     Image dst(new_w, new_h);
     for (int y=0; y < new_h; ++y)
     {
         for (int x=0; x < new_w; ++x)
              dst[y][x] = src.sample(x / (float)new_w, y / (float)new_h);
     }
     return dst;
}

ในขณะที่การใช้งานฟังก์ชั่นนั้นเปลี่ยนแปลงสถานะโลคอล (และชั่วคราว) ในรูปแบบของตัวแปรตัวนับสองตัวและอิมเมจโลคัลชั่วคราวเพื่อส่งออก แต่ก็ไม่มีผลข้างเคียงภายนอก มันใส่ภาพและเอาท์พุทใหม่ เราสามารถมัลติเธรดให้กับเนื้อหาในใจของเรา มันง่ายที่จะให้เหตุผลเกี่ยวกับและง่ายต่อการทดสอบอย่างละเอียด มันเป็นข้อยกเว้นที่ปลอดภัยเพราะถ้ามีอะไรเกิดขึ้นภาพใหม่จะถูกยกเลิกโดยอัตโนมัติและเราไม่ต้องกังวลกับการย้อนกลับผลข้างเคียงภายนอก (ไม่มีภาพภายนอกที่ถูกแก้ไขนอกขอบเขตของฟังก์ชั่นดังนั้นจะพูด)

ฉันเห็นว่าน้อยที่จะได้รับและอาจจะหายไปมากโดยการทำให้Imageไม่เปลี่ยนรูปในบริบทข้างต้นใน C ++ ยกเว้นว่าจะทำให้ฟังก์ชั่นดังกล่าวข้างต้นไม่สะดวกต่อการใช้งานมากขึ้นและอาจมีประสิทธิภาพน้อยลงเล็กน้อย

ความบริสุทธิ์

ฟังก์ชั่นที่บริสุทธิ์ (ปราศจากผลข้างเคียงภายนอก ) เป็นสิ่งที่น่าสนใจสำหรับฉันและฉันเน้นความสำคัญของการให้ความสำคัญกับพวกเขาบ่อยครั้งต่อสมาชิกในทีมแม้ใน C ++ แต่การออกแบบที่ไม่เปลี่ยนรูปแบบซึ่งโดยทั่วไปมักจะใช้บริบทและความแตกต่างกันเล็กน้อยนั้นไม่น่าสนใจสำหรับฉันเนื่องจากมีความจำเป็นตามธรรมชาติของภาษาจึงมักมีประโยชน์และเป็นประโยชน์ในการเปลี่ยนแปลงวัตถุชั่วคราวบางอย่างในกระบวนการได้อย่างมีประสิทธิภาพ สำหรับนักพัฒนาและฮาร์ดแวร์) ใช้งานฟังก์ชั่นแท้

การคัดลอกโครงสร้างที่แข็งแรงราคาถูก

คุณสมบัติที่มีประโยชน์มากที่สุดลำดับที่สองที่ฉันพบคือความสามารถในการคัดลอกโครงสร้างข้อมูลที่มีราคาถูกมากเมื่อค่าใช้จ่ายในการทำเช่นนั้นมักจะเกิดขึ้นเพื่อทำให้ฟังก์ชั่นนั้นบริสุทธิ์เนื่องจากลักษณะอินพุต / เอาท์พุตที่เข้มงวด สิ่งเหล่านี้จะไม่เป็นโครงสร้างขนาดเล็กที่สามารถใส่ลงในสแต็กได้ พวกมันจะมีโครงสร้างที่ใหญ่และหนักหน่วงเช่นเดียวกับSceneวิดีโอเกม

ในกรณีนี้ค่าใช้จ่ายในการทำสำเนาสามารถป้องกันโอกาสในการขนานที่มีประสิทธิภาพเพราะมันอาจเป็นเรื่องยากที่จะทำให้ขนานฟิสิกส์และการเรนเดอร์ได้อย่างมีประสิทธิภาพโดยไม่ต้องล็อคและคอขวดถ้ากันและกัน คัดลอกฉากเกมทั้งหมดรอบ ๆ เพื่อเอาท์พุทหนึ่งเฟรมโดยใช้ฟิสิกส์อาจไม่ได้ผลเท่ากัน อย่างไรก็ตามหากระบบฟิสิกส์นั้น 'บริสุทธิ์' ในแง่ที่ว่ามันใส่เพียงฉากและเอาออกใหม่โดยใช้ฟิสิกส์และความบริสุทธิ์นั้นไม่ได้มาจากค่าใช้จ่ายในการคัดลอกทางดาราศาสตร์มันสามารถทำงานได้อย่างปลอดภัยพร้อมกับ โหมดแสดงภาพโดยไม่มีใครรออีก

ดังนั้นความสามารถในการคัดลอกข้อมูลที่หนักหน่วงของสถานะแอปพลิเคชั่นของคุณรอบ ๆ และส่งออกเวอร์ชันใหม่ที่ถูกแก้ไขด้วยค่าใช้จ่ายน้อยที่สุดในการประมวลผลและการใช้หน่วยความจำสามารถเปิดประตูใหม่สำหรับความบริสุทธิ์และขนานได้อย่างมีประสิทธิภาพ จากวิธีการนำโครงสร้างข้อมูลถาวรมาใช้ แต่สิ่งที่เราสร้างขึ้นโดยใช้บทเรียนดังกล่าวไม่จำเป็นต้องขัดขืนอย่างเต็มที่หรือเสนออินเทอร์เฟซที่ไม่เปลี่ยนรูป (อาจใช้ copy-on-write เช่นหรือ "builder / transient") เพื่อให้บรรลุความสามารถนี้ในราคาถูก เพื่อคัดลอกและแก้ไขเฉพาะส่วนของการคัดลอกโดยไม่เพิ่มการใช้หน่วยความจำและการเข้าถึงหน่วยความจำในการค้นหาคู่ขนานและความบริสุทธิ์ในฟังก์ชัน / ระบบ / ไปป์ไลน์ของเรา

การเปลี่ยนไม่ได้

ในที่สุดก็มีการเปลี่ยนแปลงไม่ได้ซึ่งฉันคิดว่าน่าสนใจน้อยที่สุดในสามสิ่งนี้ แต่มันสามารถบังคับใช้ด้วยกำปั้นเหล็กเมื่อการออกแบบวัตถุบางอย่างไม่ได้มีวัตถุประสงค์เพื่อใช้เป็นขมับในท้องถิ่นเพื่อการทำงานที่บริสุทธิ์และในบริบทที่กว้างขึ้น ชนิดของ "ความบริสุทธิ์ระดับวัตถุ" ในทุกวิธีไม่ก่อให้เกิดผลข้างเคียงจากภายนอกอีกต่อไป (ไม่มีการกลายพันธุ์ตัวแปรสมาชิกที่อยู่นอกขอบเขตเฉพาะของวิธีการทันที)

และในขณะที่ฉันคิดว่ามันน่าสนใจน้อยที่สุดในสามภาษานี้เช่น C ++ มันสามารถทำให้การทดสอบและความปลอดภัยของเธรดและการใช้เหตุผลของวัตถุที่ไม่ใช่เรื่องเล็ก ๆ น้อย ๆ ง่ายขึ้น มันสามารถเป็นภาระในการทำงานกับการรับประกันว่าวัตถุไม่สามารถได้รับการรวมกันของรัฐที่ไม่ซ้ำกันใด ๆ นอกตัวสร้างของมันและเราสามารถผ่านมันได้อย่างอิสระแม้โดยการอ้างอิง / ตัวชี้โดยไม่ต้องพึ่งพาความมั่นคงและอ่าน เฉพาะตัววนซ้ำและหมายเลขอ้างอิงเท่านั้นและในขณะที่รับประกัน (อย่างน้อยที่สุดเท่าที่เราจะทำได้ในภาษา) ว่าเนื้อหาต้นฉบับจะไม่ถูกเปลี่ยนแปลง

แต่ฉันพบว่าคุณสมบัตินี้น่าสนใจน้อยที่สุดเพราะวัตถุส่วนใหญ่ที่ฉันเห็นว่ามีประโยชน์ในการใช้งานชั่วคราวในรูปแบบที่ไม่แน่นอนเพื่อใช้ฟังก์ชั่นที่บริสุทธิ์ (หรือแม้แต่แนวคิดที่กว้างขึ้นเช่น "ระบบบริสุทธิ์" ซึ่งอาจเป็นวัตถุหรือชุดของ ฟังก์ชั่นที่มีเอฟเฟ็กต์ขั้นสูงสุดเพียงแค่ป้อนข้อมูลบางอย่างและแสดงผลสิ่งใหม่โดยไม่ต้องสัมผัสสิ่งอื่นใด) และฉันคิดว่าสิ่งที่ไม่สามารถเปลี่ยนแปลงได้ที่นำไปสู่ความสุดโต่งในภาษาที่จำเป็นอย่างยิ่ง ฉันจะใช้มันเท่าที่จำเป็นสำหรับส่วนต่าง ๆ ของ codebase ซึ่งช่วยได้มากที่สุด

สุดท้าย:

[... ] ดูเหมือนว่าโครงสร้างข้อมูลถาวรนั้นไม่เพียงพอในการจัดการสถานการณ์ที่เธรดหนึ่งทำการเปลี่ยนแปลงที่สามารถมองเห็นเธรดอื่นได้ สำหรับเรื่องนี้ดูเหมือนว่าเราจะต้องใช้อุปกรณ์เช่นอะตอมการอ้างอิงหน่วยความจำทรานแซคชันของซอฟต์แวร์หรือแม้กระทั่งการล็อคแบบคลาสสิกและกลไกการซิงโครไนซ์

โดยธรรมชาติหากการออกแบบของคุณเรียกร้องให้มีการปรับเปลี่ยน (ในแง่ของการออกแบบระดับผู้ใช้) เพื่อให้มองเห็นหลายเธรดพร้อมกันเมื่อเกิดขึ้นเราจะกลับมาซิงโครไนซ์หรืออย่างน้อยกระดานวาดภาพเพื่อหาวิธีที่ซับซ้อน ฉันได้เห็นตัวอย่างที่ซับซ้อนมากที่ผู้เชี่ยวชาญใช้จัดการกับปัญหาประเภทต่างๆเหล่านี้ในการเขียนโปรแกรมเชิงหน้าที่)

แต่ฉันได้พบว่าเมื่อคุณได้รับการคัดลอกและความสามารถในการส่งออกโครงสร้างที่แข็งแรงบางส่วนราคาถูกอย่างที่คุณจะได้รับพร้อมกับโครงสร้างข้อมูลแบบถาวรเป็นตัวอย่างมันมักจะเปิดประตูและโอกาสมากมายที่คุณอาจ ไม่เคยคิดมาก่อนที่จะขนานรหัสที่สามารถทำงานได้อย่างสมบูรณ์เป็นอิสระจากกันในการเรียงลำดับ I / O ที่เข้มงวดของไปป์ไลน์แบบขนาน แม้ว่าบางส่วนของอัลกอริทึมจะต้องต่อเนื่องกันตามธรรมชาติคุณอาจเลื่อนการประมวลผลไปที่เธรดเดียว แต่พบว่าการพึ่งพาแนวคิดเหล่านี้ได้เปิดประตูให้ง่ายขึ้นและไม่ต้องกังวลให้ขนาน 90% ของงานหนักเช่น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.