সি # তে অস্থিতিশীল কীওয়ার্ডের চিত্রের ব্যবহার


88

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

একই প্রোগ্রামে অস্থির কীওয়ার্ড যুক্ত করা সমস্যার সমাধান করা উচিত।

এটি এমন কিছু যা আমি অর্জন করতে পরিচালিত করি না। এমনকি বেশ কয়েকবার চেষ্টা করা, অপ্টিমাইজেশন ইত্যাদি সক্ষম করা ইত্যাদি, আমি সর্বদা 'উদ্বায়ী' কীওয়ার্ড ছাড়াই একটি সঠিক আচরণ পাই।

এই বিষয় সম্পর্কে আপনার কোনও ধারণা আছে? আপনি কীভাবে একটি সাধারণ ডেমো অ্যাপ্লিকেশনটিতে এই জাতীয় সমস্যা অনুকরণ করবেন তা জানেন? এটি কি হার্ডওয়ারের উপর নির্ভর করে?

উত্তর:


102

আমি একটি কাজের উদাহরণ অর্জন করেছি!

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

আপনি যদি রিলিজ মোডে এবং ডিবাগার ছাড়াই (উদাহরণস্বরূপ Ctrl + F5 ব্যবহার করে) এই উদাহরণটি চালান তবে লাইনটি while (test.foo != 255)'যখন (সত্য)' তে অনুকূলিত হবে এবং এই প্রোগ্রামটি আর ফিরে আসবে না। তবে volatileকীওয়ার্ড যুক্ত করার পরে আপনি সর্বদা 'ওকে' পাবেন।

class Test
{
    /*volatile*/ int foo;

    static void Main()
    {
        var test = new Test();

        new Thread(delegate() { Thread.Sleep(500); test.foo = 255; }).Start();

        while (test.foo != 255) ;
        Console.WriteLine("OK");
    }
}

4
.NET 4.0 এ পরীক্ষিত, x86 এবং x64 উভয়ই - উদাহরণটি এখনও প্রযোজ্য তা নিশ্চিত করতে পারে। ধন্যবাদ! :)
রোমান স্টারকভ

4
এটা সুন্দর! আমি কখনই জানতাম না যে জেআইটি এই ধরণের অপ্টিমাইজেশন করে এবং এটি অস্থির তা অক্ষম করে।
usr ডিরেক্টরির

4
কেবল স্পষ্ট করে বললে, আপনি ফু এর ঘোষণায় "উদ্বায়ী" কীওয়ার্ড যুক্ত করছেন, তাই না?
জোকুল

21

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


6

'উদ্বায়ী' কীওয়ার্ডটি নির্দিষ্ট না করা হলে এটি ত্রুটি হওয়ার ঘটনা সত্যিই নয়, যখন নির্দিষ্ট করা হয়নি তখন ত্রুটি ঘটতে পারে। সাধারনত আপনি জানতে পারবেন কখন এই ক্ষেত্রেটি সংকলকটির চেয়ে ভাল!

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

এই আচরণটি আসলে সি ++ এর মতো একই কীওয়ার্ড নয়।

এমএসডিএন এর একটি সংক্ষিপ্ত বিবরণ রয়েছেঅস্থিরতা, পারমাণবিকতা এবং ইন্টারলকিং সম্পর্কিত বিষয়গুলির জন্য এখানে আরও গভীরতর একটি পোস্ট রয়েছে


4

কোডটি ভার্চুয়াল মেশিন দ্বারা বিমুক্ত করা হওয়ায় এটি সি # তে প্রদর্শন করা শক্ত, সুতরাং এই মেশিনটির একটি প্রয়োগের ক্ষেত্রে এটি অস্থির ছাড়াই সঠিকভাবে কাজ করে, অন্যদিকে এটি ব্যর্থ হতে পারে।

যদিও উইকিপিডিয়ায় এটি সিতে প্রদর্শিত হয় তার একটি ভাল উদাহরণ রয়েছে।

সিআই-তে একই জিনিস ঘটতে পারে যদি জেআইটি সংকলক স্থির করে যে ভেরিয়েবলের মান যে কোনওভাবে পরিবর্তন করতে পারে না এবং এভাবে মেশিন কোড তৈরি করে যা এটি আর পরীক্ষা করে না। যদি এখন অন্য কোনও থ্রেড মান পরিবর্তন করে, আপনার প্রথম থ্রেডটি এখনও লুপটিতে ধরা পড়তে পারে।

আর একটি উদাহরণ ব্যজি ওয়েটিং।

আবার, এটি সি # এর সাথেও ঘটতে পারে তবে এটি ভার্চুয়াল মেশিন এবং জেআইটি সংকলক (বা ইন্টারপ্রিটারের উপর যদি জেআইটি না থাকে ... তত্ত্বের ভিত্তিতে দৃ strongly়ভাবে নির্ভর করে তবে আমি মনে করি এমএস সর্বদা একটি জেআইটি সংকলক ব্যবহার করে এবং মনোও ব্যবহার করে) এক; তবে আপনি নিজে এটি অক্ষম করতে সক্ষম হবেন)।


4

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

using System;
using System.Threading;

namespace VolatileTest
{
  class VolatileTest 
  {
    private volatile int _volatileInt;
    public void Run() {
      new Thread(delegate() { Thread.Sleep(500); _volatileInt = 1; }).Start();
      while ( _volatileInt != 1 ) 
        ; // Do nothing
      Console.WriteLine("_volatileInt="+_volatileInt);
    }
  }

  class NormalTest 
  {
    private int _normalInt;
    public void Run() {
      new Thread(delegate() { Thread.Sleep(500); _normalInt = 1; }).Start();
      // NOTE: Program hangs here in Release mode only (not Debug mode).
      // See: http://stackoverflow.com/questions/133270/illustrating-usage-of-the-volatile-keyword-in-c-sharp
      // for an explanation of why. The short answer is because the
      // compiler optimisation caches _normalInt on a register, so
      // it never re-reads the value of the _normalInt variable, so
      // it never sees the modified value. Ergo: while ( true )!!!!
      while ( _normalInt != 1 ) 
        ; // Do nothing
      Console.WriteLine("_normalInt="+_normalInt);
    }
  }

  class Program
  {
    static void Main() {
#if DEBUG
      Console.WriteLine("You must run this program in Release mode to reproduce the problem!");
#endif
      new VolatileTest().Run();
      Console.WriteLine("This program will now hang!");
      new NormalTest().Run();
    }

  }
}

উপরে কিছু দুর্দান্ত চমত্কার ব্যাখ্যা রয়েছে, পাশাপাশি কিছু দুর্দান্ত রেফারেন্স রয়েছে। আমাকে আমার মাথা ঘুরিয়ে আনতে সাহায্য করার জন্য সকলকে ধন্যবাদ volatile( volatileআমার প্রথম প্রবৃত্তিটি কোথায় ছিল lockতার উপর নির্ভর করতে না পারার পক্ষে পর্যাপ্ত পরিমাণে জানা )।

চিয়ার্স, এবং সমস্ত মাছের জন্য ধন্যবাদ। কিথ।


দ্রষ্টব্য: "আমি দেখতে চাই: আমি খুব আসল অনুরোধের একটি ডেমো, যা ছিল আগ্রহী হতে চাই একটি স্ট্যাটিক উদ্বায়ী int- এ সঠিকভাবে আচরণ যেখানে একটি স্ট্যাটিক int- এ খারাপ।

আমি এই চ্যালেঞ্জটি চেষ্টা করেছি এবং ব্যর্থ হয়েছি। (আসলে আমি বেশ তাড়াতাড়ি ছেড়ে দিয়েছি ;-)। আমি স্থিতিশীল ভারগুলির সাথে চেষ্টা করেছিলাম তারা উদ্বিগ্ন কিনা তা নির্বিশেষে তারা "সঠিকভাবে" আচরণ করে ... এবং আমি কেন ঘটনার ব্যাখ্যাটি পছন্দ করব, যদি সত্যিই ঘটনাটি ঘটে ... তবে তা কি সংকলকটি রেজিস্টারগুলিতে স্থির ভারগুলির মানগুলিকে ক্যাশে করে না (অর্থাত্ এটি পরিবর্তে ap শিক -ঠিকানাটির একটি রেফারেন্সকে ক্যাশে করে)?

না এটি কোনও নতুন প্রশ্ন নয় ... এটি সম্প্রদায়টিকে মূল প্রশ্নের দিকে ফিরিয়ে আনার চেষ্টা।


2

জো আলবাহারীর নীচের পাঠ্যটি আমি এসেছি যা আমাকে অনেক সাহায্য করেছিল।

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

class Program
{
    public static volatile bool complete = false;

    private static void Main()
    {           
        var t = new Thread(() =>
        {
            bool toggle = false;
            while (!complete) toggle = !toggle;
        });

        t.Start();
        Thread.Sleep(1000); //let the other thread spin up
        complete = true;
        t.Join(); // Blocks indefinitely when you remove volatile
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.