همزمانی قابلتوسعه با ویژگیهای Sync
و Send
جالب است که زبان راست ویژگیهای بسیار کمی برای همزمانی دارد. تقریباً هر ویژگی همزمانی که تاکنون در این فصل درباره آن صحبت کردهایم بخشی از کتابخانه استاندارد بوده است، نه زبان. گزینههای شما برای مدیریت همزمانی محدود به زبان یا کتابخانه استاندارد نیستند؛ میتوانید ویژگیهای همزمانی خود را بنویسید یا از ویژگیهایی که دیگران نوشتهاند استفاده کنید.
با این حال، دو مفهوم همزمانی در زبان تعبیه شدهاند: ویژگیهای std::marker
به نامهای Sync
و Send
.
اجازه انتقال مالکیت بین نخها با Send
ویژگی نشانگر Send
نشان میدهد که مالکیت مقادیر نوعی که Send
را پیادهسازی
میکند میتواند بین نخها منتقل شود. تقریباً هر نوعی در راست Send
است، اما
برخی استثناها وجود دارند، از جمله Rc<T>
: این نوع نمیتواند Send
باشد زیرا
اگر یک مقدار Rc<T>
را کلون کنید و سعی کنید مالکیت کلون را به نخ دیگری منتقل
کنید، هر دو نخ ممکن است شمارش ارجاع را همزمان بهروزرسانی کنند. به این دلیل،
Rc<T>
برای استفاده در شرایط تکریسمانی طراحی شده است که نمیخواهید جریمه
عملکرد ایمنی نخ را پرداخت کنید.
بنابراین، سیستم نوعی و محدودیتهای ویژگی راست تضمین میکنند که هرگز بهطور
ناخواسته یک مقدار Rc<T>
را به صورت ناایمن بین نخها ارسال نکنید. وقتی سعی
کردیم این کار را در فهرست 16-14 انجام دهیم، خطای the trait Send is not implemented for Rc<Mutex<i32>>
دریافت کردیم. وقتی به Arc<T>
که Send
است
تغییر دادیم، کد کامپایل شد.
هر نوعی که بهطور کامل از نوعهای Send
تشکیل شده باشد بهطور خودکار به عنوان
Send
علامتگذاری میشود. تقریباً تمام نوعهای اولیه Send
هستند، به جز
اشارهگر (Pointer)های خام، که در فصل 20 درباره آنها صحبت خواهیم کرد.
اجازه دسترسی از چندین نخ با Sync
ویژگی نشانگر Sync
نشان میدهد که نوعی که Sync
را پیادهسازی میکند میتواند
از چندین نخ به آن ارجاع داده شود. به عبارت دیگر، هر نوع T
، Sync
است اگر
&T
(یک ارجاع غیرقابلتغییر به T
) Send
باشد، به این معنی که ارجاع میتواند
به صورت ایمن به نخ دیگری ارسال شود. مشابه Send
، نوعهای اولیه Sync
هستند و
نوعهایی که به طور کامل از نوعهای Sync
تشکیل شدهاند نیز Sync
هستند.
اسمارت پوینتر Rc<T>
نیز به همان دلایلی که Send
نیست، Sync
هم نیست. نوع
RefCell<T>
(که در فصل 15 درباره آن صحبت کردیم) و خانواده نوعهای مرتبط Cell<T>
نیز Sync
نیستند. پیادهسازی بررسی وامدهی که RefCell<T>
در زمان اجرا انجام
میدهد، برای نخ ایمن نیست. اسمارت پوینتر Mutex<T>
، Sync
است و میتواند
برای اشتراکگذاری دسترسی بین چندین نخ استفاده شود، همانطور که در بخش «اشتراک
یک Mutex<T>
بین چندین نخ»
مشاهده کردید.
پیادهسازی دستی Send
و Sync
ناایمن است
از آنجا که نوعهایی که از ویژگیهای Send
و Sync
تشکیل شدهاند بهطور خودکار
بهعنوان Send
و Sync
علامتگذاری میشوند، ما نیازی به پیادهسازی دستی این
ویژگیها نداریم. به عنوان ویژگیهای نشانگر، آنها حتی هیچ متدی برای پیادهسازی
ندارند. آنها فقط برای اعمال اصول مربوط به همزمانی مفید هستند.
پیادهسازی دستی این ویژگیها شامل پیادهسازی کد ناایمن در راست میشود. ما در فصل
20 درباره استفاده از کد ناایمن در راست صحبت خواهیم کرد؛ فعلاً، اطلاعات مهم این
است که ساخت نوعهای همزمان جدید که از قسمتهای Send
و Sync
تشکیل نشدهاند
نیاز به دقت زیادی دارد تا اصول ایمنی رعایت شوند. “The Rustonomicon”
اطلاعات بیشتری درباره این اصول و نحوه رعایت آنها ارائه میدهد.
خلاصه
این آخرین باری نیست که در این کتاب با همزمانی روبهرو میشوید: کل فصل بعدی بر برنامهنویسی async تمرکز دارد، و پروژه در فصل 21 از مفاهیم این فصل در یک موقعیت واقعیتر نسبت به مثالهای کوچکتر مطرحشده در اینجا استفاده خواهد کرد.
همانطور که قبلاً اشاره شد، به دلیل اینکه بخش بسیار کمی از نحوه مدیریت همزمانی در راست بخشی از زبان است، بسیاری از راهحلهای همزمانی بهعنوان crate پیادهسازی شدهاند. اینها سریعتر از کتابخانه استاندارد تکامل مییابند، بنابراین حتماً به صورت آنلاین جستجو کنید تا crateهای بهروز و پیشرفتهای که برای موقعیتهای چندریسمانی مناسب هستند را پیدا کنید.
کتابخانه استاندارد راست کانالهایی برای ارسال پیام و انواع اسمارت پوینتر، مانند Mutex<T>
و Arc<T>
، فراهم میکند که استفاده از آنها در زمینههای همزمان ایمن است. سیستم نوعی
و کنترلکننده وامدهی تضمین میکنند که کدی که از این راهحلها استفاده میکند با رقابتهای
داده یا ارجاعهای نامعتبر مواجه نمیشود. هنگامی که کد شما کامپایل شود، میتوانید مطمئن
باشید که بدون آن دسته از اشکالهای سختردیابی که در زبانهای دیگر معمول است، به خوبی
روی چندین نخ اجرا خواهد شد. برنامهنویسی همزمان دیگر مفهومی برای ترسیدن نیست:
پیش بروید و برنامههای خود را بیباکانه همزمان کنید!