পাইথনে "থ্রেড লোকাল স্টোরেজ" কী এবং আমার কেন এটি দরকার?


102

পাইথনে বিশেষত, কীভাবে চলকগুলি থ্রেডগুলির মধ্যে ভাগ করা যায়?

যদিও আমি threading.Threadবাস্তবে কখনও বুঝতে পারিনি বা ভেরিয়েবলগুলি কীভাবে ভাগ করা যায় তার উদাহরণগুলি আগে দেখিনি। এগুলি কি মূল থ্রেড এবং বাচ্চাদের মধ্যে ভাগ করা যায় বা কেবল বাচ্চাদের মধ্যে? এই ভাগ করাটি এড়াতে আমার কখন থ্রেড লোকাল স্টোরেজ ব্যবহার করা দরকার?

আমি লক ব্যবহার করে থ্রেডগুলির মধ্যে ভাগ করা ডেটাতে অ্যাক্সেস সিঙ্ক্রোনাইজ করার বিষয়ে অনেক সতর্কতা দেখেছি তবে এখনও সমস্যার সত্যিকারের উদাহরণ দেখতে পাইনি।

আগাম ধন্যবাদ!


4
শিরোনাম প্রশ্নের সাথে মেলে না। থ্রেডগুলির মধ্যে
ভাগগুলি

4
@ ক্যাসবাশ: এই প্রশ্নের আওয়াজ থেকে মাইক পড়েছিলেন যে শেয়ার করা ডেটা দ্বারা সৃষ্ট সমস্যাগুলি এড়াতে টিএলএস প্রয়োজন, তবে কোন ডেটাটি ডিফল্টরূপে ভাগ করা হয়েছিল, এটি কী দিয়ে ভাগ করা হয়েছে এবং কীভাবে এটি ভাগ করা হয়েছে তা পরিষ্কার নয়। আমি প্রশ্নের আরও ভাল মেলে শিরোনামটি সামঞ্জস্য করেছি।
শোগ

উত্তর:


85

পাইথনে, ফাংশন-স্থানীয় ভেরিয়েবলগুলি ব্যতীত সমস্ত কিছু ভাগ করা হয় (কারণ প্রতিটি ফাংশন কল স্থানীয় লোকের নিজস্ব সেট পায়, এবং থ্রেডগুলি সর্বদা পৃথক ফাংশন কল হয়)) এবং তারপরেও কেবলমাত্র ভেরিয়েবলগুলি (বস্তুর উল্লেখ করা নাম) ফাংশন স্থানীয় হয়; বস্তুগুলি তারা সর্বদা বিশ্বব্যাপী এবং যে কোনও কিছু সেগুলিকে উল্লেখ করতে পারে। Threadএকটি নির্দিষ্ট থ্রেড জন্য বস্তু এ ব্যাপারে একটি বিশেষ অবজেক্ট নয়। আপনি যদি Threadকোথাও এই বস্তুটি সঞ্চয় করেন তবে সমস্ত থ্রেড অ্যাক্সেস করতে পারে (বৈশ্বিক চলকের মতো) তবে সমস্ত থ্রেড সেই এক Threadবস্তুতে অ্যাক্সেস করতে পারে । আপনি যদি অন্য থ্রেডের অ্যাক্সেস রয়েছে এমন কোনও কিছু পরমাণুর সাথে সংশোধন করতে চান তবে আপনাকে এটি একটি লক দিয়ে রক্ষা করতে হবে। এবং সমস্ত থ্রেড অবশ্যই অবশ্যই এটি খুব একই লক ভাগ করে নেবে, বা এটি খুব কার্যকর হবে না।

আপনি যদি আসল থ্রেড-লোকাল স্টোরেজ চান তবে এটি সেখানে threading.localআসে threading.localthreads এর বৈশিষ্ট্যগুলি থ্রেডের মধ্যে ভাগ করা হয় না; প্রতিটি থ্রেড কেবল নিজেই সেখানে স্থাপন করা গুণাবলী দেখে sees আপনি যদি এর প্রয়োগ সম্পর্কে কৌতূহলী হন তবে উত্সটি আদর্শ পাঠাগারটিতে _threading_local.py এ।


4
দয়া করে নীচের বাক্যটি সম্পর্কে আরও বিশদ দিতে পারেন? "আপনি যদি এ জাতীয় থ্রেডটিতে স্রেফ তৈরি করেন নি এবং অন্য থ্রেড যে কোনও জায়গায় পেতে পারেন সেটিকে আপনি যদি পরমাণুগতভাবে সংশোধন করতে চান তবে আপনাকে এটি একটি লক দ্বারা সুরক্ষিত করতে হবে।"
চানগুহেং

@ চেঞ্জ্যুহেং: পারমাণবিক ক্রিয়াগুলি কী তা এখানে একটি ব্যাখ্যা: cs.nott.ac.uk/~psznza/G52CON/lecture4.pdf
টম বাসবি

4
@ টমবসবি: যদি সেখানে অন্য কোনও থ্রেড না পাওয়া যায় তবে আমাদের কেন এটি একটি লক দ্বারা রক্ষা করা দরকার, কেন আমাদের প্রক্রিয়াটিকে পারমাণবিক করার দরকার হয়?
চানগ্যুহেং

4
দয়া করে আপনি এর একটি দ্রুত উদাহরণ দিতে পারেন: "বস্তুগুলি সেগুলি সর্বদা বিশ্বব্যাপী থাকে এবং যে কোনও কিছু সেগুলি উল্লেখ করতে পারে"। রেফার করে অনুমান করে আপনি বোঝাচ্ছেন পড়া এবং সংযোজন / সংযোজন নয়?
পরিবর্তনশীল

@ পরিবর্তনশীল: আমি মনে করি তার অর্থ মানগুলির কোনও সুযোগ নেই
ব্যবহারকারী 1071847

79

নিম্নলিখিত কোড বিবেচনা করুন:

#/usr/bin/env python

from time import sleep
from random import random
from threading import Thread, local

data = local()

def bar():
    print("I'm called from", data.v)

def foo():
    bar()

class T(Thread):
    def run(self):
        sleep(random())
        data.v = self.getName()   # Thread-1 and Thread-2 accordingly
        sleep(1)
        foo()
>> টি ()। স্টার্ট (); টি ()। শুরু ()
আমাকে থ্রেড -২ থেকে ফোন করা হয়েছে
আমাকে থ্রেড -১ থেকে ফোন করা হয়েছে 

এখানে থ্রেডিং.লোকাল () foo () এর ইন্টারফেস পরিবর্তন না করে রান () থেকে বার () এ কিছু তথ্য পাস করার জন্য দ্রুত এবং নোংরা উপায় হিসাবে ব্যবহৃত হয়।

নোট করুন যে গ্লোবাল ভেরিয়েবলগুলি ব্যবহার করা কৌশলটি করবে না:

#/usr/bin/env python

from time import sleep
from random import random
from threading import Thread

def bar():
    global v
    print("I'm called from", v)

def foo():
    bar()

class T(Thread):
    def run(self):
        global v
        sleep(random())
        v = self.getName()   # Thread-1 and Thread-2 accordingly
        sleep(1)
        foo()
>> টি ()। স্টার্ট (); টি ()। শুরু ()
আমাকে থ্রেড -২ থেকে ফোন করা হয়েছে
আমাকে থ্রেড -২ থেকে ফোন করা হয়েছে 

এদিকে, আপনি যদি foo () এর আর্গুমেন্ট হিসাবে এই ডেটাটি পাস করার পক্ষে সক্ষম হন - এটি আরও মার্জিত এবং সু-নকশাকৃত উপায় হবে:

from threading import Thread

def bar(v):
    print("I'm called from", v)

def foo(v):
    bar(v)

class T(Thread):
    def run(self):
        foo(self.getName())

তৃতীয় পক্ষ বা দুর্বল ডিজাইন কোড ব্যবহার করার সময় এটি সর্বদা সম্ভব হয় না।


19

আপনি থ্রেড স্থানীয় স্টোরেজ ব্যবহার করে তৈরি করতে পারেন threading.local()

>>> tls = threading.local()
>>> tls.x = 4 
>>> tls.x
4

টিএলএসে সঞ্চিত ডেটা প্রতিটি থ্রেডের জন্য অনন্য হবে যা অনিচ্ছাকৃত ভাগ করে নেওয়ার বিষয়টি নিশ্চিত করতে সহায়তা করবে।


2

ঠিক প্রতিটি অন্যান্য ভাষার মতো পাইথনের প্রতিটি থ্রেডেও একই ভেরিয়েবলের অ্যাক্সেস রয়েছে। 'মূল থ্রেড' এবং শিশু থ্রেডের মধ্যে কোনও পার্থক্য নেই।

পাইথনের সাথে একটি পার্থক্য হ'ল গ্লোবাল ইন্টারপ্রেটার লক মানে একসাথে কেবল একটি থ্রেড পাইথন কোড চালিত হতে পারে। অ্যাক্সেসকে সিঙ্ক্রোনাইজ করার ক্ষেত্রে এটি খুব বেশি সহায়তা করে না, তবে সাধারণ প্রাক-শোধন সংক্রান্ত সমস্ত সমস্যা এখনও প্রয়োগ হয় এবং আপনাকে অন্যান্য ভাষার মতো থ্রেডিং আদিম ব্যবহার করতে হবে। এর অর্থ এই নয় যে আপনি যদি পারফরম্যান্সের জন্য থ্রেড ব্যবহার করেন তবে আপনাকে পুনর্বিবেচনা করা দরকার।


0

আমি এখানে ভুল হতে পারে। আপনি যদি অন্যথায় জানেন তবে দয়া করে এটি ব্যাখ্যা করুন কারণ কেন একজনকে থ্রেড স্থানীয় () ব্যবহার করা প্রয়োজন।

এই বিবৃতিটি বন্ধ বলে মনে হচ্ছে, ভুল নয়: "আপনি যদি অন্য থ্রেডের অ্যাক্সেস রয়েছে এমন কোনও কিছু পরমাণুভাবে সংশোধন করতে চান তবে আপনাকে এটি একটি লক দিয়ে রক্ষা করতে হবে।" আমি মনে করি এই বিবৃতিটি -> কার্যকরভাবে <- সঠিক তবে সম্পূর্ণ নির্ভুল নয়। আমি ভেবেছিলাম "পারমাণবিক" শব্দের অর্থ পাইথন ইন্টারপ্রেটার একটি বাইট-কোড শঙ্কা তৈরি করেছিলেন যা সিপিইউতে কোনও বাধা সংকেতের কোন জায়গা রাখেনি।

আমি ভেবেছিলাম পারমাণবিক অপারেশনগুলি পাইথন বাইট কোডের খণ্ডগুলি যা বাধা অ্যাক্সেস দেয় না। "চলমান = সত্য" এর মতো পাইথন স্টেটমেন্টগুলি পারমাণবিক। এই ক্ষেত্রে আপনাকে বাধা থেকে সিপিইউ লক করতে হবে না (আমি বিশ্বাস করি)। পাইথন বাইট কোড ব্রেকডাউন থ্রেড বাধা থেকে নিরাপদ।

পাইথন কোড "থ্রেড_ রুনিং [5] = সত্য" এর মতো পারমাণবিক নয়। পাইথন বাইট কোডের দুটি অংশ এখানে রয়েছে; এক একটি অবজেক্টের জন্য তালিকাটি () এবং অন্য কোনও বাইট কোড শঙ্ককে কোনও বস্তুর মান নির্ধারণের জন্য, এই ক্ষেত্রে তালিকায় একটি "স্থান" দিন to একটি বাধা উত্থাপন করা যেতে পারে -> <- দুটি বাইট-কোড -> খণ্ড <- এর মধ্যে। যে খারাপ জিনিস ঘটেছিল।

থ্রেড স্থানীয় () কীভাবে "পারমাণবিক" এর সাথে সম্পর্কিত? এই কারণেই বিবৃতিটি আমার কাছে ভুল দিকনির্দেশনা বলে মনে হচ্ছে। না পারলে কি বুঝাতে পারবেন?


4
এটি একটি উত্তরের মতো দেখায় তবে সমস্যাযুক্ত হিসাবে রিপোর্ট করা হয়েছিল, আমি জিজ্ঞাসা করা প্রশ্নগুলির কারণে ধরে নিয়েছি। আমি উত্তরে স্পষ্টতা জিজ্ঞাসা করা এড়াতে হবে। মন্তব্যগুলির জন্য এটিই।
ধর্মমন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.