আমি লক্ষ্য করেছি যে প্রায়শই তালিকাগুলির পরিবর্তে এবং একাধিক থ্রেড সহ সারি ব্যবহার করার পরামর্শ দেওয়া হয় .pop()
। তালিকাগুলি থ্রেড-নিরাপদ নয়, বা অন্য কোনও কারণে?
আমি লক্ষ্য করেছি যে প্রায়শই তালিকাগুলির পরিবর্তে এবং একাধিক থ্রেড সহ সারি ব্যবহার করার পরামর্শ দেওয়া হয় .pop()
। তালিকাগুলি থ্রেড-নিরাপদ নয়, বা অন্য কোনও কারণে?
উত্তর:
তালিকাগুলি এগুলি থ্রেড-নিরাপদ। সিপিথনে জিআইএল তাদের একযোগে প্রবেশের হাত থেকে রক্ষা করে এবং অন্যান্য প্রয়োগগুলি তাদের তালিকা বাস্তবায়নের জন্য সূক্ষ্ম দানযুক্ত লক বা একটি সিঙ্ক্রোনাইজড ডেটাটাইপ ব্যবহার করার যত্ন নেয়। যাইহোক, যখন তালিকা নিজেদের না দুর্নীতিগ্রস্ত একই সময়ে অ্যাক্সেস করতে প্রচেষ্টা দ্বারা যেতে পারেন, তালিকা এর ডেটা সংরক্ষিত নয়। উদাহরণ স্বরূপ:
L[0] += 1
যদি অন্য থ্রেড একই জিনিস করে তবে একটি দ্বারা আসলে এল [0] বাড়ানোর গ্যারান্টি নেই, কারণ +=
এটি কোনও পারমাণবিক ক্রিয়াকলাপ নয়। (খুব, পাইথনের খুব কম অপারেশনগুলি আসলে পারমাণবিক, কারণ তাদের বেশিরভাগই পাইথন কোডটি নির্বিচারে কল করতে পারে)) আপনার ক্যুইস ব্যবহার করা উচিত কারণ আপনি যদি কেবল একটি সুরক্ষিত তালিকা ব্যবহার করেন না , তবে রেসের কারণে আপনি ভুল আইটেমটি পেতে বা মুছতে পারেন may শর্ত।
টমাস 'চমৎকার উত্তর একটি বিন্দু নির্মল করার জন্য, এটা উল্লেখ করা উচিত যে append()
হয় থ্রেড নিরাপদ।
এটি কারণ এই যে কোনও উদ্বেগ নেই যে আমরা যখন এটি লিখতে যাই তখন ডেটা পড়া একই জায়গায় থাকবে। অপারেশন ডেটা পড়তে না, এটি শুধুমাত্র লিস্টে ডেটা লিখেছেন।append()
PyList_Append
সম্পন্ন হয়েছে। এটি সংযোজন একটি বস্তুর একটি রেফারেন্স দেওয়া হয়। সেই বস্তুর বিষয়বস্তুগুলি মূল্যায়নের পরে এবং কল করার আগে তার পরিবর্তিত হতে পারে PyList_Append
। তবে এটি এখনও একই জিনিস হবে এবং নিরাপদে সংযুক্ত হবে (যদি আপনি এটি করেন lst.append(x); ok = lst[-1] is x
তবে ok
অবশ্যই মিথ্যা হতে পারে)। আপনি যে কোডটি উল্লেখ করেছেন সেটি এতে যুক্ত হওয়া বিষয়বস্তু থেকে পড়া হয় না, এটি এন্টার্কট করা ছাড়া। এটি লিপিতে যুক্ত হওয়া তালিকাটি পড়ে এবং পুনরায় প্রকাশ করতে পারে।
L[0] += x
একটি সঞ্চালন করা হবে __getitem__
উপর L
এবং তারপর একটি __setitem__
উপর L
তাহলে - L
সমর্থন __iadd__
এটা বস্তুর ইন্টারফেসে ভিন্নভাবে একটু কাজ করবেন, কিন্তু এখনও দুটি পৃথক অপারেশন হয় L
পাইথন ইন্টারপ্রেটার পর্যায়ে (আপনি তাদের মধ্যে দেখতে হবে সংকলিত বাইটকোড)। append
বাইটকোড মধ্যে Aa একক পদ্ধতি কলে সম্পন্ন করা হয়।
remove
?
এখানে উদাহরণ ব্যাপক এখনো অ সম্পূর্ণ তালিকা এর list
অপারেশন কিনা তারা থ্রেড নিরাপদ। এখানেobj in a_list
ভাষা নির্মাণ সম্পর্কিত একটি উত্তর পাওয়ার আশা করছি ।
আমি সম্প্রতি এই কেসটি করেছি যেখানে আমার একটি থ্রেডে ধারাবাহিকভাবে একটি তালিকায় যুক্ত হওয়া দরকার, আইটেমগুলির মধ্য দিয়ে লুপটি নেওয়া এবং আইটেমটি প্রস্তুত ছিল কিনা তা পরীক্ষা করা, এটি আমার ক্ষেত্রে একটি এসিএনক্রাস্ট ছিল এবং এটি প্রস্তুত থাকলে কেবল তালিকা থেকে অপসারণ করা উচিত। আমার সমস্যাটি স্পষ্টভাবে প্রমাণিত করে এমন কোনও উদাহরণ আমি খুঁজে পেলাম না এখানে একটি উদাহরণ ক্রমাগতভাবে একটি থ্রেডে তালিকার তালিকা যোগ করা এবং একই তালিকা থেকে অন্য থ্রেডে ধারাবাহিকভাবে অপসারণ করা ত্রুটিযুক্ত সংস্করণটি ছোট সংখ্যায় সহজেই চলে তবে সংখ্যাটি যথেষ্ট বড় রাখুন এবং একটি চালান কয়েকবার এবং আপনি ত্রুটি দেখতে পাবেন
ফ্ল্যাশ সংস্করণ
import threading
import time
# Change this number as you please, bigger numbers will get the error quickly
count = 1000
l = []
def add():
for i in range(count):
l.append(i)
time.sleep(0.0001)
def remove():
for i in range(count):
l.remove(i)
time.sleep(0.0001)
t1 = threading.Thread(target=add)
t2 = threading.Thread(target=remove)
t1.start()
t2.start()
t1.join()
t2.join()
print(l)
আউটপুট যখন ERROR
Exception in thread Thread-63:
Traceback (most recent call last):
File "/Users/zup/.pyenv/versions/3.6.8/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "/Users/zup/.pyenv/versions/3.6.8/lib/python3.6/threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "<ipython-input-30-ecfbac1c776f>", line 13, in remove
l.remove(i)
ValueError: list.remove(x): x not in list
লক ব্যবহার করে এমন সংস্করণ
import threading
import time
count = 1000
l = []
lock = threading.RLock()
def add():
with lock:
for i in range(count):
l.append(i)
time.sleep(0.0001)
def remove():
with lock:
for i in range(count):
l.remove(i)
time.sleep(0.0001)
t1 = threading.Thread(target=add)
t2 = threading.Thread(target=remove)
t1.start()
t2.start()
t1.join()
t2.join()
print(l)
আউটপুট
[] # Empty list
উপসংহার
পূর্ববর্তী উত্তরে যেমন উল্লিখিত হয়েছে যে তালিকা থেকে উপাদানগুলিকে সংযোজন বা পপ করার কাজটি থ্রেড নিরাপদ, থ্রেডটি নিরাপদ নয় যা আপনি যখন একটি থ্রেডে যুক্ত হন এবং অন্যটিতে পপ করেন
with r:
স্পষ্টভাবে কল করার পরিবর্তে একটি প্রসঙ্গ পরিচালক ( ) ব্যবহার করা ভাল r.acquire()
এবংr.release()