سلام
تعدادی سوال برام پیام زده بودن دوستان درباره ی Thread در پایتون :
تو این پست یحث مقدماتی رو اشاره میکنم و سپس همیجوری تو زمانایی که برام آزاد بشه جلو تر میرم :
البته این بحث رو بنده از سایت پایتون براتون مینویسم
کار با Thread در پایتون مثل بیشتر زبان های برنامه نویسی هست ولی از اونها ساده تر !!!
· Threadهای متفاوت در یک پروسس در فضای Thread اصلی (منظور تردی هست که مربوط به کد های اجرایی شما ) اجرا میشوند ، این امر موجب به اشتراک گذاری بهتر و ارتباط بهتر Thread ها در پایتون میشود
· Threadها بعضی مواقع فرایندهای سبک وزن نامیده میشوند به این علت که فرایندهای سربار حافظه نیستند و نیاز به حافظه زیاد ندارند و همچنین در فرایندهای حجیم برای ما به صرفه تر هستند
یک ترد ( منظورم همون Thread هست << البته چی توز هم میشه ها ،،،،،، تررررد !! ) در پایتون و صد البته در بیشتر زبان ها ترد ها یک شروع ، فرایند اجرا و نتیجه را همراه خود دارند، برای اینکه بفهمیم این ترد در چه فرایندی ( اجرا ، شروع یا پایان ) هست پایتون Tracker های جالبی دارهدر زیر اصلی ترین و مقدماتی ترین کد اجرایی پایتون رو مشاهده میکنید


در مثال زیر نحوه استفاده از دستور اجرایی ترد را ببینید :

مثال :

و خروجی

همونطور که قبلا اشاره کردم پایتون زبونی ساده برای کار با تردهاست اما در نظر گرفتن نکاتی بسیار ضروریست ، لابلای این نکات به معماری تردها در پایتون نیز اشاره خواهد شد:
مهمترین مسئله ی استفاده کنندگان از ترد در پایتون ، مسئله ی Global Interpreter Lock ( به ترجمه ی بنده محدودیت کلی مترجم ( این بحث مترجم و کمپایلر در پایتون کلی بحث داره که خوبه بعدا بهش پرداخته بشه ) ) است. این مسئله فقط مجوز دسترسی یک ترد به مترجم را فراهم میکند. این مسئله به دو نکته در خود دارد : 1- معمولا به ندرت نیاز به استفاده از دستورات مربوط به محدودیت اشاره شده در ( Global Interpreter lock ) پایتون میباشد ( این مسئله نیاز به روشن شدن بیشتر دارد که در ادامه توضیح داده خواهد شد ) 2- جهت استفاده از مزایای استفاده از سیستم های چندپردازشی شما میبایست روندهای جداگانه استفاده کنید.برنامه نویس ابتدا میبایست هدف خود را در استفاده از ترد مشخص نماید. آیا هدف برنامه نویس استفاده از مزایای معماری چند هسته ای میباشد ؟ که در این صورت میبایست روندهای نرم افزار در قالبت چند روندی یا Multi Process طراحی و پیاده سازی شود. در استفاده از مزایای چند هسته ای ، روندها در پردازش های مختلف به هسته های اولویت بندی شده بوسیله ماشین مجازی پایتون و سپس بوسیله ی سیستم عامل محاسبه شده و نتیجه از همین مسیر به نرم افزار بر میگردد.
در ادامه به شرح طراحی ترد در پایتون میپردازم :

CPython ( اشاره مختصر و سریع )
جهت ادامه ی بحث مدیریت ترد ها لازم است یک سری از بسته های پایتون رو معرفی نمود.
سی پایتون از پایتون در محیط سی برگرفته شده است. این کاره ها ( برنامه نویس ها 😉 ) به جهت جدا سازی این بسته از پایتون آنرا سی پایتون میخوانند. سی پایتون رخدادیست که کد کدهای شما رو بصورت کد بایت های C به اجرا می آورد. این کدها به کدبایت های سی درآورده شده و آنها را در چرخه ی نظارتی خود ترجمه میکند. پس CPython یک مترجم کدبایتی است و در نتیجه سی پایتون را میتوان بعنوان یک مترجمی معرفی نمود که مکانیزم نوشتن به زبان پایتون و کمپایل به زبون سی معرفی کرد. (به این مقوله ( نوشتن به زبانی و کمپایل به زبونی دیگر ) Foreign Function interface نیز گفته میشود. )
حالا پس از خواندن پاراگرف بالا به بسته های زیر نیز توجه بشه بد نیست :
Jython نیز کد ها را در بایت کد های جاوایی کمپایل میکند و بشما اجازه میدهد کدهای خود را در JVM نیز به اجرا درآورید
IronPython نیز بشما اجازه میدهد کدهای خود را در Microsoft CLR اجرا نمایید.
و PyPy محیطی را فراهم میکند تا کدهای شما سریعتر از سی پاتون با همان ساختار سی پایتون اجرا شوند.
پس فهمیدیم که پایتون بسته هایی دارد که بشما اجازه میدهد کد های خود را تحت زبان های مختلف کمپایل و اجرا نمایید.

GIL یا همون Global Interpreter Lock
در سی پایتون ، GIL یک mutex است که بر تردهای مختلف اجرا کننده ی کدبایت های پایتون محدودیت هایی را اعمال می کند.
(موتکس : موتکس به ابزارهایی جهت اطمینان از اینکه هیچ دو پردازشی یا دو تردی در Critical Section بصورت همزمان اجرا نخواهند شد گفته میشود. Critical Section نیز به زمانی گفته میشود که یک روند در حال استفاده یا بررسی منابع اشتراکی میباشد ( منابع اشتراکی مثل حافظه ی به اشتراک گذاشته شده Shared Memory))
MUTEX >> wiki

Mutual_exclusion_example_with_linked_list

این محدودیت اعمال شده جزو ضرویات پایه ای سی پایتون است چون سیستم مدیریت حافظه سی پایتون thread-safe نیست و روندها رو بصورت تک پردازشی انجام میشود. پس نتیجه میگیریم مترجم پایتون یه مترجم چندپردازشی نیست ، و برای پشتیبانی از پردازش های multithread از محیط همه جانبه ای بنام GIL که در ابتدای کار میبایست بوسیله ی ترد اصلی پایتون ایجاد شده تا امکان دسترسی به آبکت های پایتون را فراهم آورد استفاده میکند.
بدون دخالت GIL حتی ساده ترین روند ها نیز میتواند در مولتی تردینگ مسئله ساز شود.

GIL :
GIL معمولا بحث برانگیز است ، به این علت که این سیستم مولتی تردهای سی پایتون را از مزایای مولتی پراسس منع می کند. ( بطور بلقوه روندهای طولانی مانند مدیریت های خروجی و ورودی یا Image Processing خارج از GIL کار میشوند. بنا بر این در برنامه های مولتی تردینگی CPython که پروسس های طولانی مدت دارند GIL را به تگنا می رسانند.
سوال : پس GIL برای مولتی تردینگ در سیستم های مولتی کور چه راهکاری دارد ؟؟ GIL رفتاری جالب و منحصربفردی در این حوزه دارد که نظر توسعه دهندگان را بخود جلب میکند J
بیایید باهم ببینیم :
این تابع به درد نخور را در نظر بگیرید :

حالا این تابع را دوبار پیاپی اجرا نمایید :

و حالا این دو را در دو ترد بصورت پارالل اجرا کنید :
فول سورس :

و اما خروجی

و در آخر نتیجه :
آخر چرا در یک سیستم 4 کور با 8 گیگ رم ترد ها با سرعت تقریبی 1.5x آهسته تر اجرا شدند ؟؟
اگه حالا برنامه رو با یک کور اجرا کنم چه اتفاقی می افتد ؟؟ بللله !!! 1.3x آهسته تر !!
حالا کمی روی این موضوع فکر کنیم J
.
.
.
.
.
. ( مثلا در حال فکر کردن هستیم ) !! @
.
.
.
.
.
.
و اما رفتار GIL
· این مسئله ساده هست : ترد ها GIL را در حین اجرا از آن خود میکنند

Untitled3

· در بالا مدلی از مولتی تردینگ که بصورت هماهنگ کار میکنند نمایش داده شده است