موضوع مقاله: حافظه تراکنشی نرم افزار | مخاطب: عمومی | لحن: دانشنامه‌ای | ساختار: عنوان، مقدمه، 3 بخش، جمع‌بندی | مقاله: | # حافظه تراکنشی نرم افزار | مقدمه: این روش جایگزینی برای همگام‌سازی مبتنی بر قفل است و در نرم‌افزار پیاده‌سازی می‌شود، نه در سخت‌افزار. | ## بخش 1: حافظه تراکنشی نرم افزار | در این زمینه، "تراکنش" به قطعه‌ای از کد اطلاق می‌شود که مجموعه‌ای از خواندن‌ها و نوشتن‌ها را روی حافظهٔ مشترک انجام می‌دهد. این عملیات به‌طور منطقی در یک لحظهٔ واحد رخ می‌دهند؛ حالت‌های میانی برای سایر تراکنش‌ها (که با موفقیت انجام می‌شوند) قابل مشاهده نیستند. ایدهٔ پشتیبانی سخت‌افزاری از تراکنش‌ها نخستین‌بار در مقاله‌ای از تام نایت در سال ۱۹۸۶ ارائه شد. در سال ۱۹۹۵، نیر شاویت و دن تویتو این مفهوم را به حافظهٔ تراکنشی صرفاً نرم‌افزاری (STM) گسترش دادند. از سال ۲۰۰۵، STM به موضوعی مهم در پژوهش‌های دانشگاهی تبدیل شده و پشتیبانی عملی از آن نیز رو به افزایش است. عملکرد برخلاف تکنیک‌های قفل‌گذاری که در بیشتر برنامه‌های چندریسمانی مدرن به کار می‌رود، STM اغلب رویکردی خوش‌بینانه دارد: یک ریسمان (thread) تغییرات خود را روی حافظهٔ مشترک بدون توجه به آن‌چه سایر ریسمان‌ها انجام می‌دهند، اعمال می‌کند و همهٔ خواندن‌ها و نوشتن‌ها را در یک گزارش (log) ثبت می‌کند. در پایان تراکنش، خواننده بررسی می‌کند که آیا تغییرات دیگری از سوی ریسمان‌های دیگر بر نواحی دسترسی‌یافته وجود داشته یا نه. در غیر این صورت، تراکنش abort می‌شود و همهٔ تغییرات آن به حالت قبل بازگردانده می‌شود. مزیت این رویکرد خوش‌بینانه افزایش هم‌زمانی است: هیچ ریسمانی نیاز به صبر برای دسترسی به یک منبع ندارد و ریسمان‌های مختلف می‌توانند به‌صورت هم‌زمان بخش‌های جداگانه‌ای از ساختار داده را تغییر دهند. با این حال، در عمل، STM در مقایسه با سیستم‌های قفل‌گذاری دقیق در تعداد کم پردازنده‌ها (۱ تا ۴) ممکن است کندتر باشد، زیرا ثبت گزارش و انجام عملیات نهایی‌سازی زمان‌بر است. با این حال، پیاده‌سازی‌های خاص می‌توانند با جلوگیری زودهنگام از تراکنش‌های ناکام، سربار را کاهش دهند. مزایا و معایب مفهومی STM علاوه‌بر مزایای عملکردی، درک مفهومی برنامه‌های چندریسمانی را ساده‌تر می‌کند و نگه‌داری برنامه‌ها را آسان‌تر می‌سازد، زیرا با انتزاع‌های سطح‌بالا مانند اشیا و ماژول‌ها سازگار است. | ## بخش 2: حافظه تراکنشی نرم افزار | در مقابل، برنامه‌نویسی مبتنی بر قفل‌گذاری با چالش‌های زیر روبرو است: نیاز به مدیریت عملیات هم‌پوشان و ناقص در بخش‌های پراکنده و غیرمرتبط کد؛ کاری دشوار و مستعد خطاست. در مقابل، مفهوم تراکنش حافظه بسیار ساده‌تر است، زیرا هر تراکنش را می‌توان به عنوان یک محاسبهٔ تک‌ریسمانی در نظر گرفت. وارونگی اولویت همچنان ممکن است، اما تراکنش‌های با اولویت بالا می‌توانند تراکنش‌های پایین‌تر را لغو کنند. همچنین، عملیات دارای اثرات جانبی (مثل ورودی/خروجی) باید در صورت لغو تراکنش قابل بازگردانی باشند. برای حل این مشکل، معمولاً بافرهایی برای جمع‌آوری عملیات غیرقابل بازگشت استفاده می‌شوند و این عملیات پس از موفقیت تراکنش اجرا می‌شوند. عملیات های ترکیبی در سال ۲۰۰۵، تیم هریس، سایمون مارلو، سایمون پیتون جونز و موریس هرلیهی یک سامانهٔ STM مبتنی بر هسکل هم‌زمان معرفی کردند که اجازه می‌دهد عملیات اتمی دلخواه را به عملیات اتمی بزرگ‌تر ترکیب کرد؛ قابلیتی که در برنامه‌نویسی مبتنی بر قفل ممکن نیست. نویسندگان مقاله توضیح می‌دهند که در برنامه‌های مبتنی بر قفل، عملیات صحیح ممکن است در ترکیب با دیگر عملیات ناکارآمد یا نادرست عمل کنند. برای مثال، فرض کنید می‌خواهیم یک عنصر را از جدول درهم‌سازی t1 حذف و در t2 وارد کنیم، بدون آن‌که حالت میانی (که در آن عنصر در هیچ‌یک از جدول‌ها وجود ندارد) قابل مشاهده باشد. مگر آن‌که پیاده‌ساز جدول چنین سناریویی را پیش‌بینی کرده باشد، راهی برای تحقق آن نیست. در سامانهٔ حافظهٔ تراکنشی نرم‌افزاری (STM)، ترکیب عملیات به‌صورت اتمی با قرار دادن آن‌ها در یک تراکنش امکان‌پذیر است. برای حل این مسئله، سازوکار «retry» پیشنهاد شده که با بررسی لاگ تراکنش، تشخیص می‌دهد چه زمانی داده‌ای تغییر کرده و تراکنش باید دوباره اجرا شود. همچنین تابعی به نام orElse معرفی شده که اجرای چند تراکنش جایگزین را امکان‌پذیر می‌کند و در صورت شکست همه، آن‌ها را پس از تغییر مرتبطی مجدداً امتحان می‌کند. | ## بخش 3: حافظه تراکنشی نرم افزار | پشتیبانی زبان پیشنهادی سادگی مفهومی STMها (حافظه تراکنشی نرم‌افزاری) باعث می‌شود بتوان آن‌ها را با استفاده از نگارش‌های نسبتاً ساده‌ی زبان‌های برنامه‌نویسی در اختیار برنامه‌نویس قرار داد. تیم هریس و کایر فریزر در مقاله‌ی خود با عنوان "پشتیبانی زبانی برای تراکنش‌های سبک‌وزن"، ایده‌ی استفاده از ساختار کلاسیک ناحیه بحرانی شرطی (CCR) را برای نمایش تراکنش‌ها مطرح کردند. این جداسازیِ ضعیف بین تولیدکننده‌ها و مصرف‌کننده‌ها باعث افزایش ماژولار بودن در مقایسه با سیگنال‌دهی صریح بین نخ‌ها (threads) می‌شود. این دستور می‌تواند در هر لحظه، تراکنش را باطل کرده و منتظر بماند تا یکی از مقادیری که قبلاً در طول تراکنش خوانده شده تغییر کند، سپس تراکنش دوباره اجرا می‌شود. با این حال، استثنا می‌تواند اطلاعاتی که در طول تراکنش تخصیص داده شده یا خوانده شده را برای اهداف عیب‌یابی حفظ کند. البته، آن‌ها تأکید می‌کنند که در دیگر محیط‌ها ممکن است تصمیمات طراحی متفاوتی نیز منطقی باشند. قفل گذاری تراکنشی STM (حافظه تراکنشی نرم‌افزاری) می‌تواند به‌صورت یک الگوریتم بدون قفل (lock-free) پیاده‌سازی شود یا از قفل‌گذاری استفاده کند. سپس، در هر عملیات خواندن یا نوشتن، نسخه‌ی مکان حافظه موردنظر با نسخه‌ی خوانده‌شده مقایسه می‌شود؛ و اگر نسخه‌ی آن بیشتر باشد، تراکنش باطل می‌شود. در مرحله‌ی commit، تمام مکان‌هایی که قرار است نوشته شوند، قفل می‌گردند و نسخه‌های تمام مکان‌های خوانده‌شده و نوشته‌شده دوباره بررسی می‌شوند. در نهایت، ساعت نسخه‌ی سراسری افزایش می‌یابد، مقادیر جدید از لاگ به حافظه بازنویسی شده و با نسخه‌ی جدید مهر زده می‌شوند مسائل مربوط به پیاده‌سازی یکی از مشکلات پیاده‌سازی حافظه تراکنشی نرم‌افزاری (STM) با استفاده از خواندن خوش‌بینانه (optimistic reading) این است که ممکن است یک تراکنش ناقص، وضعیت ناهماهنگی را بخواند؛ یعنی ترکیبی از مقادیر قدیمی و جدید که توسط یک تراکنش دیگر نوشته شده‌اند. چنین تراکنشی در صورت تلاش برای commit، قطعاً باطل خواهد شد، بنابراین این موضوع، شرط سازگاری‌ای را که توسط سیستم تراکنشی اعمال می‌شود، نقض نمی‌کند. | ## جمع‌بندی | اما ممکن است تراکنش A، مقدار x را پس از به‌روزرسانی آن توسط تراکنش B بخواند، اما مقدار y را پیش از به‌روزرسانی آن توسط همان تراکنش B بخواند.