শুনেছি আমি ++ থ্রেড নিরাপদ নয়, ++ আমি থ্রেড-নিরাপদ?


90

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

তবে আমি ++ i নিয়ে ভাবছি wond আমি যতদূর বলতে পারি, এটি একক সমাবেশ নির্দেশকে হ্রাস করবে, যেমন 'r1, r1, 1 যোগ করুন' এবং যেহেতু এটি কেবল একটি নির্দেশ, তাই এটি প্রসঙ্গের সুইচ দ্বারা নিরবচ্ছিন্ন হতে চাই।

কেউ কি স্পষ্ট করতে পারেন? আমি ধরে নিচ্ছি যে একটি x86 প্ল্যাটফর্ম ব্যবহৃত হচ্ছে।


শুধু একটা প্রশ্ন. দুটি (বা ততোধিক) থ্রেডের মতো কোন চলকের অ্যাক্সেসের জন্য কী ধরণের পরিস্থিতিগুলির প্রয়োজন হবে? আমি সৎভাবে এখানে জিজ্ঞাসা করছি, সমালোচনা করছি না। এখন এই মুহুর্তে, আমার মাথা কিছু ভাবতে পারে না।
অস্কার রাইজ

4
একটি বস্তুর গণনা বজায় রেখে C ++ শ্রেণিতে একটি বর্গ ভেরিয়েবল?
প্যাক্সডিয়াবলো

4
আমি কেবল আজ যে বিষয়টি দেখেছি তার সম্পর্কে ভাল ভিডিও কারণ অন্য একজন আমাকে বলেছেন: youtube.com/watch?v=mrvAqvtWYb4
জোহানেস স্কাউব - লিটিব

4
সি / সি ++ হিসাবে পশ্চাদপসরণ করা; জাভা এখানে বিবেচনা করা হচ্ছে না, সি # একই, কিন্তু যেমন কঠোরভাবে সংজ্ঞায়িত মেমরি শব্দার্থবিজ্ঞানের অভাব আছে।
টিম উইলিসক্রফ্ট

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

উত্তর:


158

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

এটি বেশ সম্ভাব্য যা ++iএকটি স্বেচ্ছাসেবী ক্রমের সংকলন করতে পারে যেমন:

load r0,[i]  ; load memory into reg 0
incr r0      ; increment reg 0
stor [i],r0  ; store reg 0 back to memory

যা আমার (কল্পিত) সিপিইউতে থ্রেড-নিরাপদ হবে না যার মেমোরি-ইনক্রিমেন্টের কোনও নির্দেশনা নেই। অথবা এটি স্মার্ট হতে পারে এবং এটি সংকলন করতে পারে:

lock         ; disable task switching (interrupts)
load r0,[i]  ; load memory into reg 0
incr r0      ; increment reg 0
stor [i],r0  ; store reg 0 back to memory
unlock       ; enable task switching (interrupts)

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

ভাষা নিজেই (বা এটির জন্য লাইব্রেরিগুলি যদি এটি ভাষায় নির্মিত না হয়) থ্রেড-সেফ কনস্ট্রাক্টস সরবরাহ করবে এবং কোন মেশিন কোড উত্পন্ন হবে তার আপনার বোঝার (বা সম্ভবত ভুল বোঝাবুঝির) উপর নির্ভর করে আপনার সেগুলি ব্যবহার করা উচিত।

জাভা synchronizedএবং pthread_mutex_lock()(কিছু অপারেটিং সিস্টেমের অধীনে সি / সি ++ উপলভ্য) এর মতো বিষয়গুলি যা আপনাকে (ক) দেখার প্রয়োজন


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


8
এটি জোর দেওয়ার জন্য +1 যে এটি কোনও প্ল্যাটফর্ম-নির্দিষ্ট সমস্যা নয়, একটি পরিষ্কার উত্তর উল্লেখ করা উচিত নয় ...
আরবেরটিগ

4
আপনার সি রৌপ্য ব্যাজটির জন্য অভিনন্দন :)
জোহানেস স্কাউব - 0

আমার মনে হয় আপনার অবশ্যই ঠিক করা উচিত যে কোনও আধুনিক ওএস ইউজার-মোড প্রোগ্রামগুলিকে বাধা বন্ধ করার অনুমোদন দেয় না, এবং pthread_mutex_lock () সি এর অংশ নয়
বাসটিয়েন লোনার্ড

@ বাস্টিয়ান, কোনও আধুনিক ওএস কোনও সিপিইউতে চলবে না যার মেমোরি ইনক্রিমেন্টের নির্দেশনা নেই :-) তবে আপনার বক্তব্য সি সম্পর্কে নেওয়া হয়েছে
প্যাক্সিডিয়াব্লো

4
@ বাসটিয়েন: বুল আরআইএসসি প্রসেসরের সাধারণত মেমোরি ইনক্রিমেন্টের নির্দেশ থাকে না। লোড / অ্যাড / স্টোর ট্রিপলেটটি হ'ল উদাহরণস্বরূপ, পাওয়ারপিসি how
ডার্বার্ট

42

আপনি ++ i বা i ++ সম্পর্কে কম্বল স্টেটমেন্ট দিতে পারবেন না। কেন? 32-বিট সিস্টেমে একটি 64-বিট পূর্ণসংখ্যা বৃদ্ধি বিবেচনা করুন। অন্তর্নিহিত মেশিনের কোয়াড শব্দ না থাকলে "লোড, ইনক্রিমেন্ট, স্টোর" নির্দেশনা, মানটি বাড়িয়ে একাধিক নির্দেশের প্রয়োজন হয়, যার মধ্যে কোনও থ্রেড প্রসঙ্গ সুইচ দ্বারা বাধাগ্রস্ত হতে পারে।

তদ্ব্যতীত, ++iসর্বদা "মানটিতে একটি যুক্ত করা হয় না"। সি-এর মতো ভাষায়, পয়েন্টার বাড়ানো আসলে নির্দেশিত জিনিসটির আকার যুক্ত করে। এটি, যদি i32-বাইট কাঠামোর পয়েন্টার হয় তবে ++i32 বাইট যুক্ত করা হয়। যেখানে প্রায় সব প্ল্যাটফর্মের একটি "মেমরি ঠিকানায় ইনক্রিমেন্ট ভ্যালু" নির্দেশনা রয়েছে যা পারমাণবিক, সকলেরই একটি অ্যাটমিক থাকে না "মেমরি ঠিকানার মানকে নির্বিচার মান যোগ করুন" নির্দেশনা।


35
অবশ্যই আপনি যদি সি ++ এর মতো ভাষায় 32-বিট পূর্ণসংখ্যার কাছে নিজেকে সীমাবদ্ধ না করেন তবে ++ আমি সত্যিকার অর্থে একটি ওয়েব সার্ভিসে কল হতে পারি যা একটি ডাটাবেসে কোনও মান আপডেট করে।
সূর্যগ্রহণ

16

তারা উভয় থ্রেড-অনিরাপদ।

একটি সিপিইউ সরাসরি স্মৃতি দিয়ে গণিত করতে পারে না। এটি অপ্রত্যক্ষভাবে মেমরি থেকে মান লোড করে এবং সিপিইউ রেজিস্টারগুলির সাথে গণিত করে।

আমি ++

register int a1, a2;

a1 = *(&i) ; // One cpu instruction: LOAD from memory location identified by i;
a2 = a1;
a1 += 1; 
*(&i) = a1; 
return a2; // 4 cpu instructions

++ i

register int a1;

a1 = *(&i) ; 
a1 += 1; 
*(&i) = a1; 
return a1; // 3 cpu instructions

উভয় ক্ষেত্রেই একটি রেসের শর্ত রয়েছে যার ফলশ্রুতি অপ্রত্যাশিত i মান।

উদাহরণস্বরূপ, ধরে নেওয়া যাক যথাক্রমে রেজিস্টার এ 1, বি 1 ব্যবহার করে দুটি সমান্তরাল ++ i থ্রেড রয়েছে। এবং, প্রসঙ্গের স্যুইচিংয়ের সাথে নিম্নলিখিতগুলির মতো সম্পাদন করা হয়:

register int a1, b1;

a1 = *(&i);
a1 += 1;
b1 = *(&i);
b1 += 1;
*(&i) = a1;
*(&i) = b1;

ফলস্বরূপ, আমি i + 2 হয় না, এটি i + 1 হয়ে যায়, যা ভুল।

এটির প্রতিকারের জন্য, মোডেন সিপিইউগুলি বিরতিতে কিছু প্রকারের লক, আনলক সিপিইউ নির্দেশাবলী সরবরাহ করে একটি প্রসঙ্গ স্যুইচিং অক্ষম করা হয়।

উইন 32 এ থ্রেড-সুরক্ষার জন্য আই ++ করতে ইন্টারলকডইনক্রিমেন্ট () ব্যবহার করুন। এটি মিটেক্সের উপর নির্ভর করার চেয়ে অনেক দ্রুত।


6
"একটি সিপিইউ সরাসরি মেমরি দিয়ে গণিত করতে পারে না" - এটি সঠিক নয়। সিপিইউ-গুলি রয়েছে, যেখানে আপনি প্রথমে কোনও রেজিস্টারে লোড না করে মেমরির উপাদানগুলিতে "সরাসরি" গণিত করতে পারেন। যেমন MC68000
ডার্ললন

4
লক এবং আনলক সিপিইউ নির্দেশাবলীর প্রসঙ্গ সুইচগুলির সাথে কোনও সম্পর্ক নেই। তারা ক্যাশে লাইন লক।
ডেভিড শোয়ার্জ

11

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

সম্পাদনা: একটি জিনিস আপনি বেশিরভাগ আর্কিটেকচারের সাথে ধরে নিতে পারেন তা হ'ল আপনি যদি সঠিকভাবে সারিবদ্ধ একক শব্দের সাথে কথা বলছেন তবে আপনি দুটি মানের সংমিশ্রণে একক শব্দটি শেষ করতে পারবেন না যা একসাথে ছড়িয়ে পড়েছিল। দুটি লেখাগুলি একে অপরের শীর্ষে ঘটে গেলে, একটি জিতবে এবং অন্যটি বাদ দেওয়া হবে। আপনি যদি সাবধান হন তবে আপনি এটির সুবিধা নিতে পারেন এবং দেখুন যে একক লেখক / একাধিক পাঠক পরিস্থিতিতে ++ i বা i ++ হয় থ্রেড-নিরাপদ।


বাস্তবে ভুল যেখানে পরিবেশে অ্যাক্সেস (পড়া / লেখার) পারমাণবিক at এমন অ্যালগরিদম রয়েছে যা এই জাতীয় পরিবেশে কাজ করতে পারে, যদিও মেমরির বাধার অভাব বলতে পারে আপনি কখনও কখনও বাসি ডেটাতে কাজ করছেন।
এমসাল্টাররা

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

10

আপনি যদি সি ++ তে পারমাণবিক বৃদ্ধি চান তবে আপনি সি ++ 0 এক্স লাইব্রেরি ( std::atomicডেটাটাইপ) বা টিবিবির মতো কিছু ব্যবহার করতে পারেন ।

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


"এক-শব্দ ডেটাটাইপ আপডেট করা" মন্তব্যটি স্পষ্ট করতে:

কোনও এসএমপি মেশিনে দুটি সিপিইউ একই চক্রে একই মেমোরি অবস্থানে লিখতে পারে এবং তারপরে অন্যান্য সিপিইউ এবং ক্যাশে পরিবর্তন প্রচার করার চেষ্টা করে। এমনকি যদি ডেটা কেবলমাত্র একটি শব্দ লেখা হয় তাই লেখকরা কেবল একটি চক্র সম্পূর্ণ করতে সময় নেয়, সেগুলি একই সাথে ঘটে তাই আপনি কোনটি সাফল্যের গ্যারান্টি দিতে পারবেন না। আপনি আংশিক আপডেট হওয়া ডেটা পাবেন না, তবে একটি লেখাই অদৃশ্য হয়ে যাবে কারণ এই কেসটি হ্যান্ডেল করার কোনও উপায় নেই।

তুলনা এবং অদলবদল একাধিক সিপিইউগুলির মধ্যে সঠিকভাবে সমন্বয় সাধন করে, তবে এক-শব্দের ডেটাটাইপগুলির প্রতিটি পরিবর্তনশীল অ্যাসাইনমেন্ট তুলনা এবং অদলবদল ব্যবহার করবে বলে বিশ্বাস করার কোনও কারণ নেই।

এবং যখন একটি নিখুঁত কম্পাইলার প্রভাবিত করে না কিভাবে বোঝা / দোকান কম্পাইল করা হয়, এটা পরিবর্তন করতে পারেন যখন লোড / দোকান ঘটবে, গুরুতর সমস্যা ঘটাচ্ছে যদি আপনি আশা আপনার পড়ে এবং একই আদেশ তারা সোর্স কোড প্রদর্শিত ঘটতে লিখেছেন ( সর্বাধিক বিখ্যাত হচ্ছে ডাবল-চেকড লকটি ভ্যানিলা সি ++ এ কাজ করে না)।

দ্রষ্টব্য আমার আসল উত্তরে এও বলা হয়েছে যে bit৪ বিটের ডেটা নিয়ে ইন্টেল bit৪ বিটের আর্কিটেকচারটি ভেঙে গেছে। এটি সত্য নয়, সুতরাং আমি উত্তরটি সম্পাদনা করেছি, তবে আমার সম্পাদনায় দাবি করা হয়েছে পাওয়ারপিসি চিপস নষ্ট হয়ে গেছে। নিবন্ধগুলিতে তাত্ক্ষণিক মানগুলি (অর্থাত্ ধ্রুবকগুলি) পড়ার সময় এটি সত্য ( তালিকা 2 এবং তালিকার 4 এর অধীনে "লোডিং পয়েন্টার" নামে দুটি বিভাগ দেখুন)। তবে একটি চক্রের মেমরি থেকে ডেটা লোড করার জন্য একটি নির্দেশ রয়েছে ( lmw), সুতরাং আমি আমার উত্তরের সেই অংশটি সরিয়েছি।


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

আপডেট করার জন্য ধন্যবাদ। সঠিক, পড়া এবং লেখাই পারমাণবিক হিসাবে আপনি বলেছিলেন যে তারা অর্ধ-সমাপ্ত হতে পারে না, তবে আপনার মন্তব্যটি বাস্তবে আমরা কীভাবে এই বাস্তবের কাছে পৌঁছায় তা হাইলাইট করে। স্মৃতি বাধা একই, তারা অপারেশনের পারমাণবিক প্রকৃতি প্রভাবিত করে না, তবে বাস্তবে আমরা কীভাবে এটি ব্যবহার করি।
ড্যান ওলসন 21

4

সি / সি ++ এর x86 / উইন্ডোজ এ, আপনি এটি থ্রেড-নিরাপদ বলে ধরে নেওয়া উচিত নয়। আপনার যদি পারমাণবিক ক্রিয়াকলাপের প্রয়োজন হয় তবে আপনার ইন্টারলকডইনক্রিমেন্ট () এবং ইন্টারলকডেক্রেমেন্ট () ব্যবহার করা উচিত ।


4

যদি আপনার প্রোগ্রামিংয়ের ভাষা থ্রেড সম্পর্কে কিছুই না বলে, তবুও বহুবিবাহিত প্ল্যাটফর্মে চলে, তবে কোনও ভাষা কীভাবে থ্রেড-নিরাপদ হতে পারে?

অন্যরা যেমন উল্লেখ করেছে: আপনার প্ল্যাটফর্ম নির্দিষ্ট কলগুলির মাধ্যমে ভেরিয়েবলগুলিতে যে কোনও মাল্টিথ্রেডেড অ্যাক্সেস রক্ষা করা উচিত।

প্ল্যাটফর্মের বিশিষ্টতাটিকে বিমূর্ত করে তুলতে এমন গ্রন্থাগার রয়েছে এবং আসন্ন সি ++ স্ট্যান্ডার্ডটি থ্রেডগুলি মোকাবেলার জন্য এটির মেমরির মডেলটি রূপান্তর করেছে (এবং এভাবে থ্রেড-সুরক্ষার গ্যারান্টি দিতে পারে)।


4

এমনকি যদি এটি একটি একক সমাবেশ নির্দেশে কমানো হয় তবে সরাসরি মেমরিতে মান বাড়িয়ে দেয়, এটি এখনও থ্রেড নিরাপদ নয়।

মেমরিতে মান বাড়ানোর সময়, হার্ডওয়্যার একটি "রিড-মডিফাই-রাইটিং" ক্রিয়াকলাপ সম্পাদন করে: এটি মেমরি থেকে মানটি পড়ে, বৃদ্ধি করে এবং মেমোরিতে ফিরে লেখায়। X86 হার্ডওয়্যার সরাসরি মেমোরিতে বৃদ্ধি করার কোনও উপায় নেই; র‌্যাম (এবং ক্যাশে) কেবলমাত্র মানগুলি পড়তে ও সঞ্চয় করতে সক্ষম, সেগুলি পরিবর্তন করে না।

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

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

নোট করুন যে ব্যবহার volatileএখানে সাহায্য করে না; এটি কেবলমাত্র সংকলককে বলে যে ভেরিয়েবলটি বাহ্যিকভাবে পরিবর্তিত হতে পারে এবং সেই ভেরিয়েবলটি পড়তে হবে কোনও রেজিস্টারে ক্যাশে বা অপ্টিমাইজ করা উচিত নয়। এটি সংকলক পারমাণবিক আদিম ব্যবহার করে না।

সর্বোত্তম উপায় হ'ল পারমাণবিক আদিম ব্যবহার (যদি আপনার সংকলক বা গ্রন্থাগারগুলি সেগুলি থাকে), বা সরাসরি সমাবেশে বৃদ্ধি করুন (সঠিক পারমাণবিক নির্দেশাবলী ব্যবহার করে)।


2

কখনই ধরে নিবেন না যে কোনও বর্ধনশীল পারমাণবিক ক্রিয়াকলাপকে সংকলন করবে। ইন্টারলকডইনক্রিমেন্ট বা আপনার টার্গেট প্ল্যাটফর্মে যা কিছু অনুরূপ ফাংশন বিদ্যমান ব্যবহার করুন।

সম্পাদনা: আমি এই সুনির্দিষ্ট প্রশ্নটি সন্ধান করেছি এবং এক্স 86 এর বর্ধন একক প্রসেসর সিস্টেমে পারমাণবিক, তবে মাল্টিপ্রসেসর সিস্টেমে নয়। লক উপসর্গটি ব্যবহার করা এটি পারমাণবিক তৈরি করতে পারে তবে কেবল ইন্টারলকডইনক্রিমেন্ট ব্যবহার করার জন্য এটি আরও অনেক বহনযোগ্য।


4
ইন্টারলকডইনক্রিমেন্ট () একটি উইন্ডোজ ফাংশন; আমার সমস্ত লিনাক্স বাক্স এবং আধুনিক ওএস এক্স মেশিনগুলি এক্স 64 ভিত্তিক, সুতরাং ইন্টারলকডইনক্রিমেন্ট () এক্স x86 কোডের চেয়ে 'অনেক বেশি বহনযোগ্য' বলে।
পিট কির্খাম

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

2

X86- তে এই সমাবেশ পাঠ অনুসারে , আপনি স্বতঃস্ফূর্তভাবে কোনও মেমরির স্থানে একটি রেজিস্টার যুক্ত করতে পারেন , তাই সম্ভবত আপনার কোডটি পরমাণুভাবে '++ i' বা 'আই ++' চালিয়ে যেতে পারে। তবে অন্য পোস্টে যেমন বলা হয়েছে, সি আনসিস '++' অপ্টারেশনে পরমাণু প্রয়োগ করে না, তাই আপনার সংকলকটি কী উত্পন্ন করবে তা সম্পর্কে আপনি নিশ্চিত হতে পারবেন না।


1

1998 সি ++ স্ট্যান্ডার্ডের থ্রেড সম্পর্কে কিছু বলার নেই, যদিও পরবর্তী মান (এই বছরের বা পরবর্তী কারণে) করে does সুতরাং, আপনি বাস্তবায়নের উল্লেখ না করে অপারেশনগুলির থ্রেড-সুরক্ষা সম্পর্কে বুদ্ধিমান কিছু বলতে পারবেন না। এটি কেবলমাত্র প্রসেসর ব্যবহৃত হচ্ছে তা নয়, তবে সংকলক, ওএস এবং থ্রেড মডেলের সংমিশ্রণ রয়েছে।

বিপরীতে নথিপত্রের অভাবে, আমি ধরে নেব না যে কোনও ক্রিয়া থ্রেড-নিরাপদ, বিশেষত মাল্টি-কোর প্রসেসর (বা মাল্টি-প্রসেসর সিস্টেম) সহ। থ্রেড সিঙ্ক্রোনাইজেশনের সমস্যাগুলি কেবল দুর্ঘটনাক্রমেই আসার সম্ভাবনা থাকায় আমি টেস্টগুলিতে বিশ্বাস করব না।

আপনার কাছে ডকুমেন্টেশন না থাকলে কিছুই থ্রেড-সেফ হয় না তবে এটি আপনার ব্যবহার করা নির্দিষ্ট সিস্টেমের জন্য বলে is


1

স্থানীয় থ্রেড আমি থ্রেড; এটি পারমাণবিক নয়, তবে এটি কোনও ব্যাপার নয়।


1

আফাইক, সি ++ স্ট্যান্ডার্ড অনুসারে একটি পড়তে / লিখতে intপারমাণবিক হয়।

যাইহোক, এটি যা যা করে তা হ'ল ডেটা রেসের সাথে সম্পর্কিত অনির্ধারিত আচরণ থেকে মুক্তি পাওয়া।

তবে উভয় থ্রেড বাড়ানোর চেষ্টা করলে এখনও ডেটা রেস থাকবে i

নিম্নলিখিত পরিস্থিতিতে কল্পনা করুন:

i = 0শুরুতে যাক :

থ্রেড এ মেমরি থেকে মূল্য পড়ছে এবং নিজস্ব ক্যাশে সঞ্চয় করে। থ্রেড একটি মান দ্বারা 1 বৃদ্ধি করে।

থ্রেড বি মেমরি থেকে মানটি পড়ে এবং নিজস্ব ক্যাশে সঞ্চয় করে। থ্রেড বি মান 1 দ্বারা বৃদ্ধি করে।

এটি যদি একক থ্রেড হয় তবে আপনি i = 2স্মৃতিতে পেয়ে যাবেন ।

তবে উভয় থ্রেডের সাহায্যে প্রতিটি থ্রেড তার পরিবর্তনগুলি লিখে দেয় এবং থ্রেড এ i = 1মেমরিতে ফিরে আসে এবং থ্রেড বি i = 1মেমোরিতে লিখে দেয়।

এটি ভালভাবে সংজ্ঞায়িত হয়েছে, কোনও আংশিক ধ্বংস বা নির্মাণ বা কোনও জিনিস ছিঁড়ে যাওয়ার কোনও ধরণের নেই, তবে এটি এখনও একটি ডেটা রেস।

পরমাণু বৃদ্ধির জন্য iআপনি ব্যবহার করতে পারেন:

std::atomic<int>::fetch_add(1, std::memory_order_relaxed)

রিলাক্সড অর্ডারিং ব্যবহার করা যেতে পারে কারণ এই অপারেশনটি কোথায় ঘটে সেদিকে আমরা নজর দিই না আমাদের যত্ন নেওয়া সমস্ত হ'ল ইনক্রিমেন্ট অপারেশনটি পারমাণবিক।


0

আপনি বলছেন "এটি কেবল একটি নির্দেশ, এটি প্রসঙ্গের স্যুইচ দ্বারা নিরবচ্ছিন্ন হতে হবে।" - একক সিপিইউয়ের জন্য এটি বেশ ভাল এবং ভাল তবে ডুয়াল কোর সিপিইউয়ের কী হবে? তারপরে আপনার কাছে কোনও প্রসঙ্গের সুইচ ছাড়াই একই সময়ে একই চলকটিতে অ্যাক্সেস করার জন্য দুটি থ্রেড থাকতে পারে।

ভাষা না জেনে উত্তরটি হ্যাকটিকে পরীক্ষা করে দেখানো।


4
কোনও কিছু এটি পরীক্ষা করে থ্রেড-নিরাপদ কিনা তা আপনি খুঁজে পাবেন না - থ্রেডিংয়ের সমস্যা মিলিয়ন ঘটনার মধ্যে একটি হতে পারে। আপনি আপনার ডকুমেন্টেশনে এটি সন্ধান করেন। এটি যদি আপনার ডকুমেন্টেশনের মাধ্যমে থ্রেডসেফের গ্যারান্টিযুক্ত না হয়, তা নয়।
25-28

4
এখানে @ জোশের সাথে সম্মত হন। অন্তর্নিহিত কোড বিশ্লেষণের মাধ্যমে কিছু গাণিতিকভাবে প্রমাণিত হতে পারে তবে কিছু কেবল থ্রেড-নিরাপদ। কোন পরিমাণ পরীক্ষার কাছে যেতে শুরু করতে পারে না।
রেক্স এম 3

এটি শেষ বাক্য হওয়া পর্যন্ত দুর্দান্ত উত্তর ছিল।
রব কে

0

আমি মনে করি যে "i++" বাক্যটি যদি কেবলমাত্র একটি বিবৃতিতে থাকে তবে এটি "++ i" এর সমতুল্য, সংকলকটি সাময়িক মান ইত্যাদি না রাখার জন্য যথেষ্ট স্মার্ট, তাই যদি আপনি এগুলি বিনিময়যোগ্যভাবে ব্যবহার করতে পারেন (অন্যথায় আপনি জিতেছেন) কোনটি ব্যবহার করবেন তা জিজ্ঞাসা করবেন না, তারা প্রায় একই রকম হয়ে থাকায় আপনি যা ব্যবহার করেন তা বিবেচ্য নয় (নান্দনিকতা বাদে)।

যাইহোক, ইনক্রিমেন্ট অপারেটর পারমাণবিক হলেও, এটি সঠিক গ্যারান্টি দেয় না যে আপনি সঠিক লকগুলি ব্যবহার না করলে বাকী গণনা সামঞ্জস্য থাকবে।

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


0

একটি কাউন্টারের জন্য, আমি একটি তুলনা এবং অদলবদ প্রজ্ঞাটি ব্যবহার করার পরামর্শ দিচ্ছি যা উভয়ই লকিং এবং থ্রেড-নিরাপদ।

এটি জাভাতে রয়েছে:

public class IntCompareAndSwap {
    private int value = 0;

    public synchronized int get(){return value;}

    public synchronized int compareAndSwap(int p_expectedValue, int p_newValue){
        int oldValue = value;

        if (oldValue == p_expectedValue)
            value = p_newValue;

        return oldValue;
    }
}

public class IntCASCounter {

    public IntCASCounter(){
        m_value = new IntCompareAndSwap();
    }

    private IntCompareAndSwap m_value;

    public int getValue(){return m_value.get();}

    public void increment(){
        int temp;
        do {
            temp = m_value.get();
        } while (temp != m_value.compareAndSwap(temp, temp + 1));

    }

    public void decrement(){
        int temp;
        do {
            temp = m_value.get();
        } while (temp > 0 && temp != m_value.compareAndSwap(temp, temp - 1));

    }
}

একটি টেস্ট_অ্যান্ড_সেট ফাংশনের অনুরূপ।
সমোজ

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