এটি আসলে পুনরায় প্রবেশ নয় ; আপনি একই থ্রেডে (বা বিভিন্ন থ্রেডে) দুবার কোনও ফাংশন পরিচালনা করছেন না । আপনি এটি পুনরাবৃত্তির মাধ্যমে বা অন্য ফাংশনে কলব্যাক ফাংশন-পয়েন্টার আর্গ হিসাবে বর্তমান ফাংশনের ঠিকানাটি পাস করার মাধ্যমে পেতে পারেন। (এবং এটি অনিরাপদ হবে না কারণ এটি সিনক্রোনাস হবে)।
এটি একটি সিগন্যাল হ্যান্ডলার এবং মূল থ্রেডের মধ্যে কেবল প্লেইন ভ্যানিলা ডেটা রেস ইউবি (অপরিজ্ঞাত আচরণ): কেবল এটির জন্যই sig_atomic_t
সুরক্ষিত গ্যারান্টিযুক্ত । অন্যরা কাজের ক্ষেত্রে ঘটতে পারে, যেমন আপনার ক্ষেত্রে যেখানে 8-বাইট অবজেক্টটি x86-64 এ একটি নির্দেশ দিয়ে লোড বা সঞ্চয় করা যায় এবং সংকলকটি সেই asm বাছাই করার জন্য ঘটে। (@ আইক্রাসের উত্তরগুলি দেখায়)।
এমসিইউ প্রোগ্রামিং দেখুন - লুপের সময় সি ++ ও 2 অপটিমাইজেশন বিরতি - একটি একক কোর মাইক্রোকন্ট্রোলারের একটি বিঘ্নিত হ্যান্ডলার মূলত সিঙ্গল থ্রেডেড প্রোগ্রামে সিগন্যাল হ্যান্ডলার হিসাবে একই জিনিস। সেক্ষেত্রে ইউবির ফলাফল হ'ল একটি লুপ থেকে লোড উত্তোলন হয়।
আপনার ডেটা-রেস ইউবির কারণে টিয়ার কেসটি কেস কেস সম্ভবত 32-বিট মোডে বিকাশ / পরীক্ষা করা হয়েছিল, বা কোনও পুরানো ডम्बर সংকলক সহ স্ট্রাক্ট সদস্যদের আলাদাভাবে লোড করেছে।
আপনার ক্ষেত্রে, সংকলকটি অসীম লুপ থেকে দোকানগুলি অনুকূল করে তুলতে পারে কারণ কোনও ইউবি-মুক্ত প্রোগ্রাম সেগুলি পর্যবেক্ষণ করতে পারে নি। data
হয় _Atomic
বা নাvolatile
, এবং লুপে অন্য কোনও পার্শ্ব প্রতিক্রিয়া নেই। সুতরাং কোনও পাঠকই এই লেখকের সাথে সিঙ্ক্রোনাইজ হওয়ার উপায় নেই। বাস্তবে এটি ঘটে যদি আপনি অনুকূলিতকরণ সক্ষম করে ( গডবোল্ট মূলের নীচে একটি ফাঁকা লুপ দেখায়) দিয়ে সংকলন করেন । আমি স্ট্রাক্টটি দুটি করেও পরিবর্তন করেছি long long
এবং লিসিপি এর movdqa
আগে জিসিসি একক 16-বাইট স্টোর ব্যবহার করে। (এটি গ্যারান্টিযুক্ত পারমাণবিক নয়, তবে এটি প্রায় সমস্ত সিপিইউতে অনুশীলন করা হয়েছে, ধরে নেওয়া হয়েছে যে এটি প্রান্তিককরণ করা হয়েছে, বা ইন্টেল কেবল একটি ক্যাশে-লাইন সীমানাটি অতিক্রম করে না। x86-তে প্রাকৃতিকভাবে সংযুক্ত ভেরিয়েবল অণুতে কেন পূর্ণসংখ্যক নিয়োগ রয়েছে? )
সুতরাং অপ্টিমাইজেশান সক্ষম করার সাথে সংকলন করাও আপনার পরীক্ষাকে ভঙ্গ করবে এবং প্রতিবার আপনাকে একই মান দেখায় show সি কোনও বহনযোগ্য সমাবেশের ভাষা নয়।
volatile struct two_int
সংকলককে এগুলি অপ্টিমাইটিস না করতে বাধ্য করবে, তবে এটি পুরো স্ট্রাকটকে পরমাণুগতভাবে লোড / সঞ্চয় করতে বাধ্য করবে না । (এটা চাই থামাতে পারেন এমনটি থেকে এটা, যদিও।) লক্ষ্য করুন volatile
নেই না ডেটা-জাতি UB এড়াতে, কিন্তু বাস্তবে এটা আন্ত থ্রেড যোগাযোগের জন্য যথেষ্ট এবং কিভাবে মানুষ (ইনলাইন এ এস এম সহ) হাতে ঘূর্ণিত atomics নির্মিত ছিল সাধারণ সিপিইউ আর্কিটেকচারের জন্য সি 11 / সি ++ 11 এর আগে। তারা ক্যাশে-সুসঙ্গত তাই volatile
হয় অনুশীলন বেশিরভাগই অনুরূপ _Atomic
সঙ্গেmemory_order_relaxed
বিশুদ্ধ-লোড এবং বিশুদ্ধ-স্টোর, যদি ধরনের জন্য ব্যবহার যথেষ্ট যে কম্পাইলার একটি একক নির্দেশ ব্যবহার করবে যাতে আপনি বিচ্ছিন্নকরণ পাবেন না সংকীর্ণ। এবং অবশ্যইvolatile
আইএসও সি স্ট্যান্ডার্ড বনাম লিখিত কোডের কোনও গ্যারান্টি নেই যা একই asm ব্যবহার করে _Atomic
এবং মো_রেল্যাক্সযুক্ত comp
আপনি একটি ফাংশন করেছিলাম ছিল global_var++;
একটি অন int
বা long long
আপনি মূল থেকে চালানো এবং একটি সংকেত হ্যান্ডলার থেকে অ্যাসিঙ্ক্রোনাস, যে ডেটা-জাতি UB তৈরি করতে ব্যবহার পুনরায় entrancy একটি উপায় হতে হবে।
এটি কীভাবে সংকলিত হয়েছে তার উপর নির্ভর করে (কোনও স্মৃতি গন্তব্য ইনক বা যোগ করতে বা লোড / ইনক / স্টোরকে আলাদা করতে) এটি পরমাণু হবে বা একই থ্রেডে সংকেত হ্যান্ডলারের ক্ষেত্রে নয়। 'Int num' এর জন্য num ++ পারমাণবিক হতে পারে দেখুন ? x86 এবং সি ++ এ পারমাণবিকতা সম্পর্কে আরও জানতে। ( সি 11 এর stdatomic.h
এবং _Atomic
বৈশিষ্ট্যটি সি ++ 11 এর std::atomic<T>
টেম্পলেটের সমতুল্য কার্যকারিতা সরবরাহ করে )
কোনও নির্দেশের মাঝে বাধা বা অন্যান্য ব্যতিক্রম ঘটতে পারে না, সুতরাং একটি স্মৃতি-গন্তব্য যুক্ত হ'ল পারমাণবিক কব্জি। প্রসঙ্গটি একটি একক-কোর সিপিউতে স্যুইচ করে। কেবলমাত্র একটি (ক্যাশে সুসংহত) ডিএমএ লেখক সিঙ্গল কোর সিপিইউতে প্রিফিক্স add [mem], 1
ছাড়াই একটি থেকে ইনক্রিমেন্টটি "পদক্ষেপ" করতে পারে lock
। অন্য কোনও থ্রোর নেই যা অন্য থ্রেড চলতে পারে।
সুতরাং এটি সংকেতের ক্ষেত্রে অনুরূপ: একটি সংকেত হ্যান্ডলারটি সূচিত হ্যান্ডলিং করে থ্রেডের সাধারণ সম্পাদনের পরিবর্তে চলতে থাকে , সুতরাং এটি একটি নির্দেশের মাঝখানে পরিচালনা করা যায় না।