بیایید قبل از اینکه راه حل را ببینیم، اول مشکل را دقیق تر برسی کنیم. به این فکر کنید که شما یک فایلی دارید که شامل یک عدد است که اشاره میکند به مقدار اعتباری که کاربر در حسابش دارد. حالا اگر قرار باشد یک پورسه اون مقدار را بر اساس ارائه سرویسی، از حساب کاربر کم کند، و پروسه دیگری به دلیل افزایش اعتبار، مقداری را به حساب کاربر اضافه کند، چه مشکلاتی اتفاق میافتد؟
برای اینکه دقیق تر بشیم، این روند رو باهم پیش میبریم. فرض کنید فایلی به اسم amount.txt مقدار 100 داخلش نوشته شده است. و دو پروسه کم و اضافه کردن را اجرا میکنیم. توی این مثال، ما میخواهیم مقدار 20 از حساب کاربر کم و مقدار 50 به حساب کاربر اضافه کنیم، پس ما انتظار داریم در انتها فایل ما مقدار 130 را درونش ذخیره کرده باشد.
- پروسه اول فایل را میخواند و مقدار 100 را در حاظهاش نگه میدارد
- پروسه دوم فایل را میخواند و مقدار 100 را در حاظهاش نگه میدارد
- پروسه اول مقدار 20 را از 100 کم میکند و مقدار 80 را در حافظه ذخیره میکند
- پروسه دوم مقدار 50 را به 100 اضافه میکند و مقدار 150 را در حافظه ذخیره میکند
- پروسه اول مقدار 80 را در فایل ذخیره میکند
- پروسه دوم مقدار 150 را در فایل ذخیره میکند
همینطور که همه ما انتظار داشتیم، ما باید در این فایل مقدار 130 را ذخیره میکردیم، اما پروسه های ما به دلیل اینکه هیچ همکاری و یا هیچ مکانیزمی دیگری ندارند که این مقدار ها را به یکدیگر اطلاع دهند، مشکل Race condition رخ میدهد.
یکی از راه حل های این مشکل lock کردن فایل توسط هر پروسه است، که به این کار file locking گفته میشود.
file locking یک مکانیزم برای کنترل دسترسی چندین پروسه به یک فایل است.
توی لینوکس یکی از دستورات خطرناکی که داریم دستور sudo rm -rf / است. وقتی این دستور را اجرا کنیم کل فایل های لینوکس ما حذف میشود. دلیل اینکار این است که لینوکس به صورت پیشفرض فایل های باز شده را lock نمیکند.
با اینحال لینوکس دو مکانیزم مختلف advisory و mandatory را پشتیبانی میکند.
توی این پست بیشتر تمرکز من روی مکانیزم advisory locking(مشورتی) است.
این روش به این شکل عمل میکند که هیچ پروسهای مجبور به اجرای این روش نیست و اگر حتی فایل توسط یک پروسهای lock شده باشد، باز هم پروسه های دیگر میتوانند به lock بودن فایل اهمیت ندهند و مقدار آن را تغییر دهند. این اتفاق به این دلیل میافتد که advisory lock توسط سیستم عامل و یا فایل سیستم انجام نمیشود.
خب بیایید با یک مثال این فرایند را برسی کنیم. مثل مثال قبلی فرض کنید ما مقدار 100 را داخل فایل amount.txt داریم و میخواهیم مقدار 20 از آن کم و مقدار 50 به آن اضافه کنیم.
- پروسه اول قبل از خواندن فایل، فایل را لاک میکند
- پروسه دوم برای لاک کردن فایل اقدام میکند و از جایی که پروسه اول از پیش فایل را لاک کرده است، برای آزاد شدن لاک صبر میکند
- پروسه اول مقدار 20 را از 100 کم میکند و مقدار 80 را درون فایل مینویسد
- پروسه اول لاک فایل را آزاد میکند.
- پروسه دوم فایل را لاک و مقدار جدید 80 را از فایل میخواند
- پروسه دوم مقدار 50 را به 80 اضافه و مقدار 120 را درون فایل مینویسد
- پروسه دوم لاک فایل را آزاد میکند تا پروسه های دیگر بتوانند با فایل کار کنند.
اگر شما میخواهید این مکانیزم را روی یک فایل اجرا کنید، دستور flock برای شما اینکار را خواهد کرد.
|
|
این کامند در حالت عادی از شما یک فایل و یک دستور خواهد گرفت و مکانیزم advisory lock را روی ان فایل اجرا خواهد کرد.
|
|
برای اینکه روند را بهتر درک کنیم یک فایل bash مینویسیم که بتوانیم مثال اولیه را روی آن اجرا کنیم.
|
|
ما این فایل را همزمان با دو ترمینال اجرا میکنیم.
همینطور که میبینید پروسه دوم برای اینکه محتوای فایل را تغییر دهد، باید صبر کند تا لاک فایل آزاد شود.
این پست خلاصهای بود از این بلاگ که هر دو نوع advisory lock و mandatory lock را توضیح میدهد.
برای من سوال بود که من چطور میتوانم مکانیزمی که
flock
استفاده میکند را در برنامه های خودم پیاده سازی کنم، و خب نتیجه این بود که معمولا برای
advisory lock
هر زبانی یک کتابخانه استاندار دارد
توی
پایتون کتابخانه
fcntl
اینکار را انجام میدهد.