سلام دوست عزیزی در مورد چگونگی پیاده
سازی یک برنامه چند نخی(Multithreaded) به طوریکه یکی از نخ ها وظیفه دادن دستوراتی رو به سایرین برای اجرا داشته
باشه سوال کرده بودند و نمونه کدی هم خواسته بودند.
در
پاسخ به این دوست عزیز باید عرض کنم، درخواست شما کدی معادل Thread
Pool است.
البته نمی شه گفت دقیقا به عمومیت Thread Pool ها چرا که تعریف و
کاربرد اونها عمومی تر از سوال شما است. در اینجا من چگونگی پیاده سازی کد مورد
نظرتون رو با استفاده از زبان پرل (Perl) توضیح میدم. در پیاده سازی از این زبان استفاده شده چون در صورت
استفاده از زبان C حجم کد بسیار زیاد خواهد شد به علاوه از جاوا (Java) هم استفاده نکردم چون
جزئیات مربوط به OOP Decomposition و شیء گرا کردن راه حل اون رو پیچیده تر می کنه.
use threads;
use threads::shared;
use Thread::Queue;
#Our global lock variable that is used as a
condition variable.
my $lock_var :shared=0;
#These
two queues are used by manager and other threads for communication
my $cmd_queue =Thread::Queue->new();
my $response_queue =Thread::Queue->new();
#Manager code comes here
if(($cmd_queue->pending())==0)
{
lock $lock_var;
$cmd_queue->enqueue($command);
cond_broadcast($lock_var);
}
else
{
#TODO: Do something else
}
sub thread
{
my $timeout;
my $is_timeout=0;
lock $lock_var;
my $timeout= time() + 10;
$is_timeout=cond_timedwait($lock_var,$timeout);
if(!$is_timeout)
{
# If waked up because of the timeout elpased
}
else
{
# If a cond_broadcast occurres
}
}
برای
پیاده سازی این راه حل از دو صف : یکی برای ارسال دستورات از طرف مدیر به نخ ها و
دیگری برای ارسال پاسخ از نخ ها به مدیر استفاده شده است. توجه داشته باشید که صف
های مورد استفاده کاملا Thread-Safe می باشند و بنابراین در صورتیکه از هر زبان برنامه نویسی دیگری
استفاده می نمایید باید در صورت وجود از ساختار داده ای Thread-Safe استفاده کنید و یا در
صورتیکه این ساختار را خودتان پیاده سازی می نمایید از انحصار متقابل (Mutual
Exclusion) به
منظور جلوگیری از دسترسی چندین نخ به صورت همزمان به المانی یکسان و تغییر آن
استفاده نمایید.
به
علاوه دو صف از یک متیغر نیز به عنوان Condition Variable یا متیر شرطی استفاده
شده است. روند کار بدین صورت است که تمامی نخ ها پس از ایجاد شدن برای بازه زمانی
خاصی که بوسیله متغیر $timeout مشخص می شود (در اینجا 10 ثانیه) بلاک می شوند در صورتیکه در این
بازه مدیر پارامتری را در صف قرار دهد با استفاده از متغیر سیگنالی به تمامی نخ ها
ارسال کرده و موجب خارج شدن آنها از حالت انسداد می شود در غیر اینصورت نخ ها می
توانند در صورت سپری شدن بازه زمانی از حالت انسداد خارج شده و عمل به خصوصی را
انجام دهند. تشخیص اینکه خارج شدن نخ ها از حالت انسداد به علت ارسال سیگنال از
طرف مدیر بوده و یا به دلیل سپری شدن بازه زمانی را با یک دستور if و با توجه به مقدار
بازگشتی تابع cond_timedwait انجام می دهیم(برای جزئیات به perldoc مراجعه نمایید).
برای
ارسال پارامتر ها به نخ ها می توان از شناسه هر نخ به عنوان فیلد اول پارامتر
استفاده نمود به این ترتیب تمامی نخ ها پس از خروج از حالت انسداد با استفاده از
تابع peek صف را بررسی کرده و به دنبال پارامتر مورد نظر خود می گردند و در
صورت یافتن آن را با استفاده از تابع extract استخراج و پردارش می
نمایند.
به
دلیل ماهیت گذرای (Transient) سیگنال های ارسالی به متغیرهای شرطی در صورت باقی ماندن پارامتر
در صف مدیر به صورت مداوم و تا زمان خالی شدن صف فرمان سیگنالی را به تمامی نخ ها
ارسال می نماید.
امیدوارم مورد استفاده قرار بگیره.