برنامه نویسی چند نخی در پایتون
در حوزهی برنامه نویسی، یک نخ (thread) کوچک ترین واحد اجرایی مستقل است. یک برنامه با استفاده از نخها میتواند به صورت همزمان به اجرای چندین عملیات در یک فضای فرایند بپردازد. یک نخ دارای یک نقطهی شروع، دنبالهی اجرا و یک نتیجه است و همچنین دارای نشانگر دستورالعمل است که وضعیت فعلی نخ را نگه داشته و ترتیب اجرای دستورات بعدی را کنترل میکند. بنابراین توانایی یک فرایند برای اجرای چندین نخ به صورت موازی را میتوان چند نخی (multithreading) نامید. چند نخی میتواند عملکرد هر برنامه را به صورت قابل توجهی بهبود ببخشد. مکانیزم برنامه نویسی چند نخی در پایتون بسیار ساده بوده و به راحتی قابل یادگیری است.
مزایای برنامه نویسی چند نخی
- باعث افزایش بهره وری کد خواهد شد و اجرای سریعتر فرآیند میشود.
- به ما این این امکان را میدهد که در برنامه در حین انجام اعمال ورودی و خروحی responsive بماند. این قابلیت خود را در برنامههای گرافیکی (GUI) بیشتر به چشم میآید.
- تمام نخهای یک برنامه میتوانند به متغیرهای سراسری برنامه دسترسی پیدا کنند و همچنین نخها میتوانند متغیرهای محلی برای خود داشته باشند.
معایب برنامه نویسی چند نخی
- در سیستمهای تک پردازندهای، نه تنها multithreading کمک چندانی به سرعت محاسبات نمیکند، بلکه ممکن است باعث شود که کارایی سیستم به دلیل سربار کنترل نخها پایین بیاید.
- برای جلوگیری از انحصار متقابل (زمانی که دو فرآیند وارد ناحیه بحرانی خود میشوند) نیاز داریم تا منابع مشترک را همگام نگه داریم، که باعث میشود بهرهگیری از حافظه و پردازنده بیشتر شود.
- پیچیدگی برنامه را زیاد و عملیات اشکالزدایی (debugging) را سخت میکند.
- احتمال ایجاد بن بست را در برنامه زیاد میکند.
- در صورت کنترل نکردن منابع مشترک، ممکن است قحطی برای نخها ایجاد شود.
در پایتون دو کتابخانه thread و threading برای برنامه نویسی چند نخی وجود دارد. کتابخانهی thread در پایتون ۳ منسوخ شده و به منظور سازگاری با نسخههای قبلی به thread_ تغییر نام داده است. کتابخانهی دیگری هم در پایتون ۳ به نام threading وجود دارد. تفاوت اصلی این دو کتابخانه این است که کتابخانه thread هر نخ را به صورت یک تابع پیاده سازی میکند؛ اما کتابخانهی threading از رویکردی شی گرا برای ایجاد نخ استفاده میکند. در این مقاله به بحث در مورد کتابخانهی threading میپردازیم.
در این مقاله تمامی کدها با پایتون 3.5 نوشته شده است.
نحوه کار با کتابخانهی threading
کتابخانهی threading دارای چندین متد است که در پیادهسازی نخها به ما کمک میکند.
- run: این متد نقطه ورود هر نخی است.
- start: وظیفه این متد راه اندازی نخهاست زمانی که متد run فراخوانی شود.
- join: این متد به برنامه این امکان را میدهد تا برای خاتمه دادن نخها منتظر بماند.
- isAlive: متدی است که نشان دهندهی فعال بودن یا نبودن نخ است.
- getName: با این متد میتوان نام نخ را بازیابی کرد.
- setName: توسط این متد میتوان نخ را نام گذاری کرد.
قدمهای ایجاد نخ
- زیر کلاسی از کلاس Thread ایجاد میکنیم.
- متد __init__ را طبق نیاز خود override میکنیم.
- در آخر هم متد run را با توجه به منطق برنامه مینویسیم.
زمانی که زیر کلاس ساخته شد، باید از آن نمونهای بسازیم و سپس متد start را فراخوانی کنیم. متد start پیکربندیهای اولیهی ساخت نخ را انجام میدهد و سپس متد run را فراخوانی میکند.
برای مثال در کد زیر 4 نخ ایجاد میکنیم و پایان آن را خواهیم دید.
import threading import time class MyThread(threading.Thread): def run(self): print("{} started!".format(self.getName())) time.sleep(1) print("{} finished!".format(self.getName())) if __name__ == '__main__': for x in range(4): mythread = MyThread(name = "Thread-{}".format(x + 1)) mythread.start() time.sleep(.5) ''' Output: Thread-1 started! Thread-2 started! Thread-1 finished! Thread-3 started! Thread-2 finished! Thread-4 started! Thread-3 finished! Thread-4 finished! '''
همگام سازی نخها
کتابخانه threading عملکردی برای قفل کردن نخها دارد. عملیات قفل کردن به ما این امکان را میدهد تا حافظه مشترک را مدیریت و از خراب شدن دادهها جلوگیری کنیم.
برای قفل کردن از متد Lock استفاده میکنیم. سپس با استفاده از متد acquire قفل را فعال و با متد release آزاد میکنیم.
در مثال زیر قفلی را تعریف میکنیم و نحوه کار با آن را خواهیم دید.
import threading import time class myThread (threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print ("\nStarting" + self.name) threadLock.acquire() print_time(self.name, self.counter, 3) threadLock.release() def print_time(threadName, delay, counter): while counter: time.sleep(delay) print ("%s: %s" % (threadName, time.ctime(time.time()))) counter -= 1 if __name__=="__main__": threadLock = threading.Lock() threads = [] thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) thread1.start() thread2.start() threads.append(thread1) threads.append(thread2) for t in threads: t.join() print ("Exiting Main Thread") ''' Output: StartingThread-1 StartingThread-2 Thread-1: Sun Jul 15 15:07:51 2018 Thread-1: Sun Jul 15 15:07:52 2018 Thread-1: Sun Jul 15 15:07:53 2018 Thread-2: Sun Jul 15 15:07:55 2018 Thread-2: Sun Jul 15 15:07:57 2018 Thread-2: Sun Jul 15 15:07:59 2018 Exiting Main Thread '''
کلام آخر
در این مقاله سعی شد که به صورت ساده مبانی برنامه نویسی چند نخی گفته شود. طبیعی است که تمام قابلیتهای این کتابخانه به مباحث گفته شده ختم نخواهد شد. برای مطالعه بیشتر میتوانید به این لینک مراجعه کنید.
دیدگاهتان را بنویسید
برای نوشتن دیدگاه باید وارد بشوید.