آموزش پایتون - نخ اصلی

در پایتون، نخ اصلی (main thread) نخستین نخ اجرایی است که هنگام اجرای مفسر پایتون آغاز به کار می‌کند. این نخ، نخ پیش‌فرض در یک فرآیند پایتون است و مسئولیت مدیریت برنامه و ایجاد نخ‌های اضافی را بر عهده دارد. هر برنامه پایتون حداقل دارای یک نخ اجرا به نام نخ اصلی است.

نخ اصلی به‌صورت پیش‌فرض یک نخ غیردیمل (non-daemon) است. در این آموزش، توضیحات مفصل را همراه با مثال‌های مرتبط درباره نخ اصلی در برنامه‌نویسی پایتون خواهید دید.

دسترسی به نخ اصلی

ماژول threading در پایتون توابعی برای دسترسی به نخ‌ها ارائه می‌دهد. توابع کلیدی عبارت‌اند از −

  • threading.current_thread(): این تابع یک نمونه از threading.Thread را برمی‌گرداند که نشان‌دهنده نخ فعلی است.
  • threading.main_thread(): یک نمونه از threading.Thread را برمی‌گرداند که نشان‌دهنده نخ اصلی است.

مثال

تابع threading.current_thread() یک نمونه از threading.Thread برمی‌گرداند که نشان‌دهنده نخ فعلی است. در ادامه یک مثال آورده شده است.

import threading

name = 'Tutorialspoint'
print('Output:', name)
print(threading.current_thread())

این کد خروجی زیر را تولید خواهد کرد −

Output: Tutorialspoint
<_MainThread(MainThread, started 140260292161536)>    

مثال

این مثال نحوه استفاده از تابع threading.main_thread() را برای دریافت ارجاع به نخ اصلی نشان می‌دهد. همچنین تفاوت بین نخ اصلی و سایر نخ‌ها را با استفاده از تابع threading.current_thread() نمایش می‌دهد.

import threading
import time

def func(x):
   time.sleep(x)
   if not threading.current_thread() is threading.main_thread():
      print('threading.current_thread() not threading.main_thread()')

t = threading.Thread(target=func, args=(0.5,))
t.start()

print(threading.main_thread())
print("Main thread finished")

هنگامی که کد بالا اجرا می‌شود، نتیجه زیر را تولید می‌کند −

<_MainThread(MainThread, started 140032182964224)>
Main thread finished
threading.current_thread() not threading.main_thread()

رفتار نخ اصلی در پایتون

نخ اصلی هر زمان که اجرای تمام کدهای موجود در اسکریپت شما که در یک نخ جداگانه آغاز نشده‌اند را به پایان برساند، خارج می‌شود. برای نمونه، زمانی که یک نخ جدید را شروع می‌کنید با استفاده از متد start()، نخ اصلی به اجرای کدهای باقی‌مانده در اسکریپت ادامه می‌دهد تا به انتهای آن برسد و سپس خارج شود.

از آنجا که سایر نخ‌ها به‌صورت پیش‌فرض در حالت غیردیمل (non-daemon) شروع می‌شوند، حتی اگر نخ اصلی خارج شده باشد، به اجرا ادامه می‌دهند تا کار خود را تمام کنند.

مثال

مثال زیر رفتار نخ اصلی را در یک برنامه چندنخی پایتون نشان می‌دهد.

import threading
import time

def func(x):
   print('Current Thread Details:',threading.current_thread())
   for n in range(x):
      print('Internal Thread Running', n)
   print('Internal Thread Finished...')

t = threading.Thread(target=func, args=(6,))
t.start()

for i in range(3):
   print('Main Thread Running',i)
print("Main Thread Finished...")

این کد خروجی زیر را تولید خواهد کرد −

Current Thread Details: Thread(Thread-1 (func), started 140562647860800)>
Main Thread Running 0
Internal Thread Running 0
Main Thread Running 1
Main Thread Running 2
Internal Thread Running 1
Main Thread Finished...
Internal Thread Running 2
Internal Thread Running 3
Internal Thread Running 4
Internal Thread Running 5
Internal Thread Finished...
کد بالا ممکن است در اجراهای مختلف و کامپایلرهای مختلف خروجی‌های متفاوتی تولید کند.

منتظر ماندن نخ اصلی برای سایر نخ‌ها

برای اطمینان از اینکه نخ اصلی منتظر می‌ماند تا تمام نخ‌های دیگر به پایان برسند، می‌توانید با استفاده از متد join() نخ‌ها را الحاق (join) کنید. با استفاده از متد join() می‌توانید جریان اجرای برنامه را کنترل کرده و اطمینان حاصل کنید که نخ اصلی پیش از خروج، به درستی منتظر می‌ماند تا همه نخ‌های دیگر کارهای خود را به پایان برسانند. این امر به مدیریت مؤثر چرخه حیات نخ‌ها در یک برنامه چندنخی پایتون کمک می‌کند.

مثال

این مثال نحوه مدیریت صحیح نخ اصلی و اطمینان از خروج نساختن آن پیش از پایان یافتن کارهای نخ‌های کارگر (worker threads) را نشان می‌دهد.

from threading import Thread
from time import sleep

def my_function_1():
   print("Worker 1 started")
   sleep(1)
   print("Worker 1 done")

def my_function_2(main_thread):
   print("Worker 2 waiting for Worker 1 to finish")
   main_thread.join()
   print("Worker 2 started")
   sleep(1)
   print("Worker 2 done")

worker1 = Thread(target=my_function_1)
worker2 = Thread(target=my_function_2, args=(worker1,))

worker1.start()
worker2.start()

for num in range(6):
   print("Main thread is still working on task", num)
   sleep(0.60)

worker1.join()
print("Main thread Completed")

هنگامی که کد بالا اجرا می‌شود، نتیجه زیر را تولید می‌کند −

Worker 1 started
Worker 2 waiting for Worker 1 to finish
Main thread is still working on task 0
Main thread is still working on task 1
Worker 1 done
Worker 2 started
Main thread is still working on task 2
Main thread is still working on task 3
Worker 2 done
Main thread is still working on task 4
Main thread is still working on task 5
Main thread Completed

پیشرفت مطالعه: وضعیت خوانده‌شدن این درس فقط در همین مرورگر ذخیره می‌شود؛ بدون نیاز به حساب کاربری.