GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing python.github.io — تضمینهای ایمنی نخ تضمینهای ایمنی نخ¶این صفحه تضمینهای ایمنی نخی برای انواع توکار در ساخت نخآزاد (free-threaded) پایتون را مستند میکند. تضمینهای توصیفشده در اینجا زمانی اعمال میشوند که از پایتون با GIL غیرفعال (حالت نخآزاد) استفاده میکنید. هنگامی که GIL فعال باشد، بیشتر عملیاتها بهطور ضمنی بهصورت سریالی اجرا میشوند. برای راهنمایی کلی درباره نوشتن کد نخایمن (thread-safe) در پایتون نخآزاد، به پشتیبانی پایتون از نخبندی آزاد مراجعه کنید. سطوح ایمنی نخ¶مستندات C API از سطوح زیر برای توصیف تضمینهای ایمنی نخی هر تابع استفاده میکند. این سطوح از کمایمنترین تا ایمنترین فهرست شدهاند. ناسازگار¶تابع یا عملیاتی که حتی با همگامسازی خارجی نیز نمیتوان آن را برای استفاده همزمان ایمن کرد. کد ناسازگار معمولاً به وضعیت سراسری بهصورت همگامنشده دسترسی پیدا میکند و باید در طول عمر برنامه تنها از یک نخ فراخوانی شود. مثال: تابعی که وضعیت سراسریِ فرایند را تغییر میدهد، مانند هندلرهای سیگنال یا متغیرهای محیطی، که در آن فراخوانیهای همزمان از هر نخی، حتی با قفلگذاری خارجی، میتوانند با رانتایم یا کتابخانههای دیگر تداخل داشته باشند. سازگار¶تابع یا عملیاتی که فراخوانی آن از چندین نخ ایمن است، مشروط بر اینکه فراخواننده همگامسازی خارجی مناسبی را فراهم کند، برای مثال با نگهداشتن یک قفل در طول مدت هر فراخوانی. بدون چنین همگامسازیای، فراخوانیهای همزمان ممکن است باعث ایجاد شرایط رقابتی یا رقابتهای دادهای شوند. مثال: تابعی که از یک شیء میخواند یا در آن مینویسد، و وضعیت داخلی آن شیء با یک قفل محافظت نمیشود. فراخوانیکنندگان باید اطمینان حاصل کنند که هیچ دو نخی بهطور همزمان به همان شیء دسترسی نداشته باشند. ایمن برای اشیاء متمایز¶تابع یا عملیاتی که فراخوانی آن از چند نخ بدون همگامسازی خارجی امن است، مشروط بر اینکه هر نخ روی یک شیء متفاوت عمل کند. دو نخ میتوانند تابع را همزمان فراخوانی کنند، اما نباید شیء یکسان (یا اشیایی که وضعیت زیربنایی مشترکی دارند) را بهعنوان آرگومان ارسال کنند. مثال: تابعی که فیلدهای یک ساختار را با استفاده از نوشتنهای غیراتمی تغییر میدهد. دو نخ میتوانند هر کدام تابع را روی نمونهی ساختار خود بهصورت ایمن فراخوانی کنند، اما فراخوانیهای همزمان روی همان نمونه به همگامسازی خارجی نیاز دارند. ایمن روی اشیاء مشترک¶تابع یا عملیاتی که برای استفاده همزمان روی همان شیء ایمن است. پیادهسازی از همگامسازی داخلی (مانند قفلهای بهازای هر شیء یا بخشهای بحرانی) برای محافظت از وضعیت تغییرپذیر مشترک استفاده میکند، بنابراین فراخوانکنندگان نیازی به فراهم کردن قفلگذاری خودشان ندارند. مثال: میتوان اتمی¶تابع یا عملیاتی که نسبت به سایر نخها بهصورت اتمی به نظر میرسد؛ از دید سایر نخها بهصورت آنی اجرا میشود. این قویترین شکل ایمنی نخی است. مثال: ایمنی در برابر نخها برای اشیای فهرست¶خواندن یک عنصر از یک lst[i] # list.__getitem__ متدهای زیر فهرست را پیمایش میکنند و از خواندنهای اتمی هر آیتم برای انجام وظیفه خود استفاده میکنند. این بدان معناست که ممکن است نتایجی برگردانند که تحت تأثیر تغییرات همزمان قرار گرفتهاند: item in lst lst.index(item) lst.count(item) همهی عملیاتهای بالا از کسب قفلهای بهازای هر شیء خودداری میکنند. آنها تغییرات همزمان را مسدود نمیکنند. سایر عملیاتهایی که قفلی را در اختیار دارند، این عملیاتها را از مشاهدهی وضعیتهای میانی باز نمیدارند. از این پس، همهی عملیاتهای دیگر با استفاده از per-object lock مسدود میشوند. نوشتن یک آیتم واحد از طریق عملیات زیر اشیای جدیدی را برمیگردانند و برای نخهای دیگر اتمی به نظر میرسند: lst1 + lst2 # concatenates two lists into a new list x * lst # repeats lst x times into a new list lst.copy() # returns a shallow copy of the list متدهای زیر که تنها روی یک المان عمل میکنند و نیازی به جابهجایی ندارند، اتمی هستند: lst.append(x) # append to the end of the list, no shifting required lst.pop() # pop element from the end of the list, no shifting required متد متد عملیاتهای زیر ممکن است به عملیات lock-free اجازه دهند که وضعیتهای میانی را مشاهده کنند، زیرا چندین المان را بهصورت درجا تغییر میدهند: lst.insert(idx, item) # shifts elements lst.pop(idx) # idx not at the end of the list, shifts elements lst *= x # copies elements in place متد فراخوانی بهطور مشابه، انتساب به یک اسلایس فهرست با عملیاتهایی که شامل چندین دسترسی و همچنین تکرار هستند، هرگز اتمی نیستند. برای مثال: # NOT atomic: read-modify-write lst[i] = lst[i] + 1 # NOT atomic: check-then-act if lst: item = lst.pop() # NOT thread-safe: iteration while modifying for item in lst: process(item) # another thread may modify lst هنگام اشتراکگذاری نمونههای ایمنی نخی برای اشیاء دیکشنری¶ایجاد یک دیکشنری با سازندهی عملیات و توابع زیر بدون قفل و اتمی هستند. d[key] # dict.__getitem__ d.get(key) # dict.get key in d # dict.__contains__ len(d) # dict.__len__ تمام عملیاتهای دیگر از اینجا به بعد، per-object lock را در اختیار دارند. نوشتن یا حذف یک آیتم واحد برای فراخوانی از چندین نخ ایمن است و دیکشنری را خراب نمیکند: d[key] = value # write del d[key] # delete d.pop(key) # remove and return d.popitem() # remove and return last item d.setdefault(key, v) # insert if missing این عملیاتها ممکن است کلیدها را با استفاده از عملیاتهای زیر شیءهای جدید را برمیگردانند و در طول مدت عملیات، per-object lock را نگه میدارند: d.copy() # returns a shallow copy of the dictionary d | other # merges two dicts into a new dict d.keys() # returns a new dict_keys view object d.values() # returns a new dict_values view object d.items() # returns a new dict_items view object متد عملیات زیر هر دو دیکشنری را قفل میکنند. برای d.update(other_dict) # both locked when other_dict is a dict d |= other_dict # both locked when other_dict is a dict d == other_dict # both locked for dict and subclasses تمام عملیاتهای مقایسه نیز مقادیر را با استفاده از
dict.fromkeys(a_dict) # locks both dict.fromkeys(a_set) # locks both dict.fromkeys(a_frozenset) # locks both هنگام بهروزرسانی از یک پیمایشپذیر غیر از دیکشنری، فقط دیکشنری هدف قفل میشود. ممکن است پیمایشپذیر بهطور همزمان توسط نخ دیگری تغییر داده شود: d.update(iterable) # iterable is not a dict: only d locked d |= iterable # iterable is not a dict: only d locked dict.fromkeys(iterable) # iterable is not a dict/set/frozenset: only result locked عملیاتهایی که شامل چندین دسترسی هستند، و همچنین پیمایش، هرگز اتمی نیستند: # NOT atomic: read-modify-write d[key] = d[key] + 1 # NOT atomic: check-then-act (TOCTOU) if key in d: del d[key] # NOT thread-safe: iteration while modifying for key, value in d.items(): process(key) # another thread may modify d برای جلوگیری از مشکلات زمان بررسی تا زمان استفاده (TOCTOU)، از عملیات اتمی استفاده کنید یا استثناها را مدیریت کنید: # Use pop() with default instead of check-then-delete d.pop(key, None) # Or handle the exception try: del d[key] except KeyError: pass برای پیمایش ایمن روی دیکشنریای که ممکن است توسط نخ دیگری تغییر داده شود، روی یک نسخه از آن پیمایش کنید: # Make a copy to iterate safely for key, value in d.copy().items(): process(key) هنگام اشتراکگذاری نمونههای ایمنی نخی برای اشیای مجموعه¶تابع عملیات خواندن زیر بدون قفل است. این عملیات تغییرات همزمان را مسدود نمیکند و ممکن است وضعیتهای میانیِ عملیاتی را که قفل بهازای هر شیء را در اختیار دارند، مشاهده کند: elem in s # set.__contains__ این عملیات ممکن است عناصر را با استفاده از از این نقطه به بعد، تمام عملیاتهای دیگر قفل بهازای هر شیء را نگه میدارند. افزودن یا حذف یک المان منفرد را میتوان بهصورت امن از چند نخ فراخوانی کرد و مجموعه خراب نمیشود: s.add(elem) # add element s.remove(elem) # remove element, raise if missing s.discard(elem) # remove element if present s.pop() # remove and return arbitrary element این عملیاتها همچنین عناصر را مقایسه میکنند، بنابراین همان ملاحظات متد متد عملیاتهای زیر فقط s |= other # other must be set/frozenset s &= other # other must be set/frozenset s -= other # other must be set/frozenset s ^= other # other must be set/frozenset s & other # other must be set/frozenset s | other # other must be set/frozenset s - other # other must be set/frozenset s ^ other # other must be set/frozenset
گونههای بهروزرسانی متدهای بالا نیز تفاوتهایی با یکدیگر دارند:
متدهای زیر همیشه تلاش میکنند هر دو شیء را قفل کنند: s.isdisjoint(other) # both locked s.issubset(other) # both locked s.issuperset(other) # both locked عملیاتهایی که شامل چندین دسترسی هستند، و همچنین پیمایش، هرگز اتمی نیستند: # NOT atomic: check-then-act if elem in s: s.remove(elem) # NOT thread-safe: iteration while modifying for elem in s: process(elem) # another thread may modify s هنگام اشتراکگذاری نمونههای ایمنی نخی برای اشیاء bytearray¶
ایمنی نخ برای اشیای memoryview¶اشیای پیادهسازی memoryview از عملیات اتمی برای پیگیری اکسپورتهای خود در free-threaded build استفاده میکند. ایجاد و آزادسازی یک memoryview نخایمن (thread-safe) هستند. دسترسی به ویژگیها (برای مثال، با این حال، دادهی واقعی که از طریق memoryview به آن دسترسی دارید، متعلق به شیء زیربنایی است. دسترسی همزمان به این داده تنها در صورتی امن است که شیء زیربنایی از آن پشتیبانی کند:
# NOT safe: concurrent writes to the same buffer data = bytearray(1000) view = memoryview(data) # Thread 1: view[0:500] = b'x' * 500 # Thread 2: view[0:500] = b'y' * 500 # Safe: use a lock for concurrent access import threading lock = threading.Lock() data = bytearray(1000) view = memoryview(data) with lock: view[0:500] = b'x' * 500 تغییر اندازه یا تخصیص مجدد شیء زیرین (مانند فراخوانی
© حق نشر 2001 Python Software Foundation.
این صفحه تحت مجوز بنیاد نرمافزار پایتون نسخه ۲ منتشر شده است. مثالها، دستورالعملها، و سایر کدهای موجود در مستندات همچنین تحت مجوز بدون بند BSD منتشر شدهاند. برای اطلاعات بیشتر به تاریخچه و مجوز مراجعه کنید. بنیاد نرمافزار پایتون یک شرکت غیرانتفاعی است. لطفاً کمک مالی کنید. آخرین بهروزرسانی در نوامبر 12, 2026 (06:19 UTC). آیا اشکالی یافتید؟ ساخته شده با Sphinx 9.1.0. |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |