امیررضا ریاحی
امیررضا ریاحی
خواندن ۷ دقیقه·۳ سال پیش

نخ‌ها و مقایسه آن‌ها با پروسه‌ها

این مطلب صرفا چکیده و خلاصه‌ای از مطالبی است که خوانده‌ام و برای تثبیت و درک بهتر مفاهیم سعی کردم آن‌ها را در قالب یک پست منتشر کنم. لذا احتمالا ایرادات فنی و حتی غیر فنی در آن وجود داشته باشد. از خواننده‌گان ممنون می‌شوم اگر این ایرادات و اشکالات را به من اطلاع بدهند.

پیش‌نویس: تا جایی که من گشتم، متاسفانه ترجمه خوبی برای کلمه thread در زبان فارسی وجود ندارد. اما از آنجایی که نوشتن خود کلمه thread در رسم‌الخط انگلیسی برای نگارنده سخت است و خواندن کلمه ترد در رسم‌الخط فارسی احتمالا برای خواننده سخت باشد، ترجیح من استفاده از همین ترجمه نیم‌بند نخ بود. اگر کسی از خواننده‌گان ترجمه معقول‌تری از این کلمه می‌داند، ممنون می‌شوم به من اطلاع بدهد.

در نوشتار قبلی تا حد مختصری سعی کردم مفهوم پروسه را تشریح کنم. در این پست قصد دارم تا درمورد نخ‌ها و جایگاه آن‌ها در مقایسه با پروسه‌ها در حد سواد خودم صحبت کنم. قبل از شروع صحبت درمورد خود مفهوم نخ، بنظرم بهتر است تفاوت concurrency و paralelism را بررسی کنیم.

parallelism همانطور که از نامش پیداست، یعنی موازی کاری. با داشتن چند پردازنده (حداقل ۲ پردازنده) کامپیوتر می‌تواند چند پروسه را در آن واحد پیش ببرد. پس با این حساب می‌توان نتیجه گرفت روی کامپیوترهای تک‌پردازنده‌ای (single-processor) موازی کاری ممکن نیست.


concurrency یعنی پیش بردن چند پروسه به صورت نوبتی در بازه‌های زمانی بسیار کوتاه. یعنی پردازنده بخش کوچکی از پروسه ۱ را انجام می‌دهد، بعد بخش کوچکی از پروسه ۲ را انجام می‌دهد. بعد دوباره برمی‌گردد به پروسه ۱ و بخش دیگری از آن را انجام می‌دهد. توجه داشته باشید که در این نوع پردازش، در آن واحد بیش از ۱ پروسه پردازش نمی‌شود. صرف دو پروسه به صورت نوبتی پیش برده می‌شوند. اما چون در بازه‌های زمانی بسیار کوتاه هر دو به نوبت اجرا می‌شوند، احتمالا برای کاربر این تصور به وجود می‌آید که هر دو پروسه به صورت همزمان اجرا می‌شوند. واضح است که این نوع از پردازش بر روی پردازنده‌های تک‌هسته‌ای هم قابل پیاده‌سازی است.



همانطور که در پست قبل توضیح داده شد، جابجایی دو پروسه یا همان context switch هزینه زمانی برای پردازنده دارد. همچنین منابع بین دو پروسه کاملا تفکیک شده‌اند از یک‌دیگر بجز در مواقع خاص. لذا ارتباط بین دو پروسه سخت و زمان‌بر است، و از طرف دیگر هر پروسه بخش نسبتا زیادی از حافظه را اشغال می‌کند. این دو مسئله باعث شدند که مفهومی به نام نخ یا همان thread وارد دنیای سیستم‌عامل شود. نخ‌ها فرایند‌های پردازشی هستند. هر نخ حتما متعقل به یک پروسه هست. همچنین در خیلی از مواقع چندین نخ متعقل به یک پروسه هستند. یا به عبارت دیگر، یک پروسه می‌تواند، شامل چندین نخ باشد.

نخ‌های متعقل به پروسه واحد، منابع زیادی را به صورت اشتراکی استفاده می‌کنند. مانند فایل‌های متعقل به آن پروسه و حافظه. اما هر پردازنده در آن واحد توانایی پیش‌بردن تنها یک نخ را دارد. لذا نخ‌ها در مدت زمان بهره‌برداری از پردازنده به صورت اشتراکی عمل نمی‌کنند. در واقع سیستم‌عامل در مدت زمانی محدود پردازنده‌ را در اختیار آن پروسه می‌گذارد. این وظیفه پروسه‌ است که این زمان را بین نخ‌های خود تقسیم کند. همچنین از آن‌جایی که در نهایت هر نخ پردازش جداگانه‌ای دارد، پس هر نخ register های خاص خود را در پردازنده لازم دارد و همچنین program counter خاص خود را دارد. این دو مورد هم جزو منابعی بودند که نخ‌ها به اشتراک نمی‌گذارند.

شاید در ابتدا و با این تفاسیر، خواننده نخ‌ها را نوعی پروسه کوچک‌تر فرض کند. البته که این تصور خیلی‌هم نادرست نیست، اما دقیق‌هم نیست. شاید تصور بهتر و دقیق‌تر این باشد که ما اصولا ماهیت پروسه‌ها و نخ‌ها را متفاوت بدانیم. به این صورت که پروسه را صرفا اجتماعی از منابع کامپیوتر بدانیم. هر پروسه، صرفا بخشی از حافظه، فضایی از دیسک و تعدادی فایل است. همچنین مدت زمانی از پردازنده و دیگر دستگاه‌های کامپیوتر مانند کیبورد و مانیتور استفاده می‌کند. اجتماع این منابع، می‌شود یک پروسه. و خب واضح است که اجتماع منابع، هیچ پردازشی را به خودی خود به همراه ندارد. در نتیجه، یک پروسه به تنهایی هیچ‌کاری را از پیش نمی‌برد. چیزی که ماهیت پردازشی دارد، همان نخ‌ است. نخ‌ یک فرایند پردازشی، زیر مجموعه یک پروسه است، که از منابع پروسه در راستای اجرا برنامه و پیش‌بردن پردازش خود استفاده می‌کند. با این تعبیر، همه پروسه‌ها باید حداقل ۱ نخ داشته باشند. تصویر زیر تا حدی این موضوع را به نمایش می‌گذارد.


سوالی که الان ممکن است برای خواننده پیش بیاید، این است که وقتی می‌توانیم یک پروسه جدید همراه با یک نخ، تولید کنیم، چه لزومی دارد به پروسه قبلی نخ‌های بیشتری اضافه کنیم؟

در واقع همیشه این الزام وجود ندارد که به پروسه قبلی نخ اضافه کنیم. اضافه کردن پروسه در مقابل اضافه کردن نخ جدید، یک معامله است. هر کدام معایب و محاسنی دارند. به این معایب و محاسن در ادامه بیشتر می‌پردازیم.

مزایای استفاده از نخ‌های بیشتر در یک پروسه

  • بعضی وقت‌ها ما نیازی به پردازش سریع نداریم. بیشتر از آن نیاز به پاسخ‌گو بودن سریع کامپیوتر داریم. مثلا وقتی یک برنامه گرافیکی اجرا شده است و در هر لحظه ممکن است کاربر روی کیبورد چیزی بنویسد یا موس خود را جابجا کند، کامپیوتر پردازش زیادی برای انجام ندارد، اما مجبور است گوش به زنگ باشد تا هر وقت موس جابجا شد یا کاربر دکمه‌ای از کیبورد را فشرد، سریعا نتیجه آن را در صفحه نمایش بدهد. در این شرایط برای ما ارجحیت دارد قدرت پردازشی کامپیوتر بین چندین نخ تقسیم شود تا اینکه یک نخ قدرت پردازشی زیادی داشته باشد. در حالت دیگر فرض کنید کامپیوتری در حال محاسبه عدد اول بسیار بزرگی است. در این حالت احتمالا داشتن چند نخ و پردازش هم‌زمان آن‌ها کمک چندانی به ما نکند و اتفاقا به دلیل بار پردازشی context switch بین هر دو نخ، احتمالا گزینه مطلوب‌تر این باشد که تمام توان پردازشی کامپیوتر در اختیار یک نخ باشد.
  • اشتراک منابع، چیزی است که برای ما در بعضی موقعیت‌ها بسیار مهم است. بعضی برنامه‌های بزرگ، مانند یک مرورگر، احتمالا از منابع مشترکی استفاده می‌کنند اما یک نخ واحد قادر به پیش‌بردن تمام آن برنامه نیست. برای همین احتمالا هر صفحه‌ای که در یک مرورگر باز می‌شود نخ جدیدی در پروسه اصلی خود مرورگر باشد. اشتراک داشتن منابع از ۲ جنبه برای ما سودمند است. جنبه اول صرفه‌جویی در مصرف حافظه است، و جنبه دوم ارتباط سریع‌تر و راحت‌تر بین نخ‌ها. از آن‌جایی که حافظه اختصاص داده شده بین نخ‌های متعلق به یک پروسه مشترک است، ارتباط راحت‌تر و سریع‌تر بین نخ‌ها تا حدی واضح است. اما دلیل صرف‌جویی در مصرف حافظه در ادامه توضیح داده خواهد شد.


همانطور که در تصویر بالا نشان داده شده است، نخ‌های متعلق به پروسه واحد، بخش program code و heap مشترک دارند. این باعث می‌شود استفاده از نخ‌های بیشتر در مقابل پروسه‌های بیشتر به صرفه‌تر باشد. در مثال قبل، فرض کنید یک مرورگر بجای نخ‌های متعدد، از پروسه‌های متعدد استفاده کند. این یعنی به ازاء هر پروسه، کل برنامه مرورگر در حافظه بارگذاری شود، که خب طبیعتا به صرفه نیست.

معایب استفاده از نخ‌های بیشتر در یک پروسه

  • همان‌طور که به عنوان یک مزیت، دسترسی آسان به اطلاعات دیگر نخ‌ها (در واقع به کل اطلاعات یک پروسه)، مطرح شد، می‌توان این را یک عیب و چالش نیز دانست. این مسئله ۲ مشکل برای ما به‌وجود می‌آورد. مشکل اول خطر تغییر اطلاعاتی است توسط دیگر نخ‌ها مورد استفاده است. وقتی هر نخ اجازه خواندن و نوشتن اطلاعات دیگر داده‌ها را دارد، طبیعتا احتمال خراب شدن داده‌ها بالا می‌رود. دومین مشکل وقتی رخ می‌دهد که دو نخ به طور هم‌زمان نیاز به دسترسی به یک داده خاص داشته باشند. به این حالت اصطلاحا race condition گفته می‌شود. این اتفاق معمولا موجب خراب شدن اطلاعات می‌شود.
  • کند شدن پردازش، چیزی که احتمالا بدیهی است. طبیعتا در نگاه اول می‌توان متوجه این نکته شد که تقسیم زمان پردازش بین نخ‌های مختلف باعث می‌شود نهایتا پردازش هر کدام دیرتر انجام شود.

همان‌طور که گفته شد، یکی از معایب استفاده از نخ‌های زیاد، نداشتن حافظه اختصاصی برای هر نخ است. این باعث می‌شود نخ‌ها امکان خراب کردن اطلاعات دیگر نخ‌ها را داشته باشند. برای اینکه این مشکل تا حدی حل شود، حافظه‌ای با نام Thread local storage ابداع شد. این حافظه در واقع حافظه اختصاصی هر نخ محسوب می‌شود که دیگر نخ‌ها به آن دسترسی ندارند. اگرچه این ابداع، تا حدی مشکل ما را حل می‌کند، اما بازهم باید توجه داشت، که حافظه TLS خیلی محدود و کوچک است.

مدل استخر نخ‌ها برای استفاده بهینه‌تر از نخ‌ها

(چقدر نخ ترجمه مزخرفیه!)

ایجاد یک نخ جدید، برای کامپیوتر هزینه دارد. اختصاص دادن یک حافظه اختصاصی و همچنین اضافه کردن اطلاعات نخ جدید به Process control block پروسه مادر و بسیاری دیگر از جزئیات آن زمان‌بر هستند. برای همین یک استراتژی برای استفاده از نخ‌های زیاد ایجاد یک استخری (یا در واقع مخزنی) از نخ‌هاست. فرض کنید یک سرور دارید. به ازاء هر درخواستی که از بیرون میاید، این سرور قرار است یک نخ جدید ایجاد کند و نخ جدید سعی کند درخواست را رتق و فتق کند. اینکار با توجه به سربار بالای ایجاد یک نخ جدید احتمالا خیلی منطقی نباشد. کاری که شاید بهتر باشد این است که در ابتدا تعداد زیادی نخ ایجاد کنیم، هرگاه درخواستی از بیرون آمد، یکی از این نخ‌ها مشغول بررسی و پاسخ دادن به آن درخواست می‌شود. در واقع کار ایجاد یک نخ جدید، در ابتدا برنامه انجام شده، و فقط باید یک نخ‌ را صدا زد.



سیستم عاملthreads
شاید از این پست‌ها خوشتان بیاید