జావా మెమరీ మోడల్‌కు పరిచయం

జావా మెమరీ మోడల్ (JMM) జావా రన్‌టైమ్ వాతావరణంలో థ్రెడ్‌ల ప్రవర్తనను వివరిస్తుంది. మెమరీ మోడల్ అనేది జావా భాష యొక్క అర్థశాస్త్రంలో భాగం, మరియు సాఫ్ట్‌వేర్‌ను అభివృద్ధి చేస్తున్నప్పుడు ప్రోగ్రామర్ ఏమి చేయవచ్చో మరియు ఏమి ఆశించకూడదో వివరిస్తుంది, కానీ ఒక నిర్దిష్ట జావా మెషీన్ కోసం కాదు, మొత్తం జావా కోసం.

1995లో అభివృద్ధి చేయబడిన అసలైన జావా మెమరీ మోడల్ (ముఖ్యంగా, "పెర్కోలోకల్ మెమరీ"ని సూచిస్తుంది), వైఫల్యంగా పరిగణించబడుతుంది: కోడ్ భద్రత యొక్క హామీని కోల్పోకుండా అనేక ఆప్టిమైజేషన్‌లు చేయలేము. ప్రత్యేకించి, బహుళ-థ్రెడ్ "సింగిల్" వ్రాయడానికి అనేక ఎంపికలు ఉన్నాయి:

  • సింగిల్‌టన్‌ను యాక్సెస్ చేసే ప్రతి చర్య (ఆబ్జెక్ట్ చాలా కాలం క్రితం సృష్టించబడినప్పటికీ, మరియు ఏమీ మారనప్పటికీ) ఇంటర్-థ్రెడ్ లాక్‌కి కారణమవుతుంది;
  • లేదా నిర్దిష్ట పరిస్థితులలో, సిస్టమ్ అసంపూర్తిగా ఉన్న ఒంటరిని జారీ చేస్తుంది;
  • లేదా నిర్దిష్ట పరిస్థితులలో, సిస్టమ్ ఇద్దరు ఒంటరి వ్యక్తులను సృష్టిస్తుంది;
  • లేదా డిజైన్ నిర్దిష్ట యంత్రం యొక్క ప్రవర్తనపై ఆధారపడి ఉంటుంది.

అందువలన, మెమరీ మెకానిజం పునఃరూపకల్పన చేయబడింది. 2005లో, జావా 5 విడుదలతో, ఒక కొత్త విధానం అందించబడింది, ఇది జావా 14 విడుదలతో మరింత మెరుగుపడింది.

కొత్త మోడల్ మూడు నియమాలపై ఆధారపడి ఉంటుంది:

నియమం #1 : సింగిల్-థ్రెడ్ ప్రోగ్రామ్‌లు నకిలీ-సీక్వెన్షియల్‌గా అమలవుతాయి. దీని అర్థం: వాస్తవానికి, ప్రాసెసర్ గడియారానికి అనేక కార్యకలాపాలను నిర్వహించగలదు, అదే సమయంలో వారి క్రమాన్ని మారుస్తుంది, అయితే, అన్ని డేటా డిపెండెన్సీలు అలాగే ఉంటాయి, కాబట్టి ప్రవర్తన సీక్వెన్షియల్ నుండి భిన్నంగా ఉండదు.

నియమం సంఖ్య 2 : ఎక్కడా లేని విలువలు లేవు. ఏదైనా వేరియబుల్‌ని చదవడం (అస్థిరత లేని పొడవు మరియు రెట్టింపు తప్ప, ఈ నియమం కలిగి ఉండకపోవచ్చు) డిఫాల్ట్ విలువ (సున్నా) లేదా మరొక ఆదేశం ద్వారా అక్కడ వ్రాసిన దాన్ని అందిస్తుంది.

మరియు నియమం సంఖ్య 3 : మిగిలిన సంఘటనలు క్రమంలో అమలు చేయబడతాయి, అవి కఠినమైన పాక్షిక ఆర్డర్ సంబంధంతో అనుసంధానించబడి ఉంటే "ముందు అమలు చేస్తుంది" ( ముందు జరుగుతుంది ).

ముందు జరుగుతుంది

లెస్లీ లాంపోర్ట్ అంతకు ముందు హ్యాపెన్స్ అనే కాన్సెప్ట్‌తో ముందుకు వచ్చింది . ఇది అటామిక్ కమాండ్‌ల (++ మరియు -- పరమాణువు కాదు) మధ్య పరిచయం చేయబడిన కఠినమైన పాక్షిక క్రమం సంబంధం మరియు "భౌతికంగా ముందు" అని అర్థం కాదు.

మొదటి బృందం చేసిన మార్పుల గురించి రెండవ బృందం "తెలుసుకుంటుంది" అని చెప్పింది.

ముందు జరుగుతుంది

ఉదాహరణకు, అటువంటి ఆపరేషన్ల కోసం ఒకటి మరొకటి ముందు అమలు చేయబడుతుంది:

సమకాలీకరణ మరియు మానిటర్లు:

  • మానిటర్‌ను సంగ్రహించడం ( లాక్ పద్ధతి , సమకాలీకరించబడిన ప్రారంభం) మరియు దాని తర్వాత అదే థ్రెడ్‌లో ఏది జరిగినా.
  • మానిటర్ యొక్క రిటర్న్ (పద్ధతి అన్‌లాక్ , సమకాలీకరించబడిన ముగింపు) మరియు దానికి ముందు అదే థ్రెడ్‌లో ఏది జరిగినా.
  • మానిటర్‌ను తిరిగి ఇవ్వడం మరియు దానిని మరొక థ్రెడ్ ద్వారా క్యాప్చర్ చేయడం.

రాయడం మరియు చదవడం:

  • ఏదైనా వేరియబుల్‌కి వ్రాసి, అదే స్ట్రీమ్‌లో చదవడం.
  • అస్థిర చరరాశికి వ్రాసే ముందు ప్రతిదీ అదే థ్రెడ్‌లో ఉంటుంది మరియు రచన కూడా. అస్థిర పఠనం మరియు దాని తర్వాత అదే థ్రెడ్‌లోని ప్రతిదీ.
  • అస్థిర చరరాశికి వ్రాసి, దాన్ని మళ్లీ చదవడం. అస్థిర వ్రాత మానిటర్ రిటర్న్ మాదిరిగానే మెమరీతో సంకర్షణ చెందుతుంది, అయితే రీడ్ క్యాప్చర్ లాగా ఉంటుంది. ఒక థ్రెడ్ అస్థిర చరరాశికి వ్రాసినట్లయితే మరియు రెండవది దానిని కనుగొంటే, వ్రాసే ముందు ఉన్న ప్రతిదీ చదివిన తర్వాత వచ్చే ప్రతిదానికీ ముందు అమలు చేయబడుతుంది; చిత్రాన్ని చూడండి.

వస్తువు నిర్వహణ:

  • స్టాటిక్ ఇనిషియలైజేషన్ మరియు ఆబ్జెక్ట్‌ల యొక్క ఏవైనా సందర్భాలతో ఏదైనా చర్యలు.
  • కన్స్ట్రక్టర్‌లోని తుది ఫీల్డ్‌లకు మరియు కన్స్ట్రక్టర్ తర్వాత ప్రతిదానికీ వ్రాయడం. మినహాయింపుగా, సంభవించే ముందు సంబంధం ఇతర నియమాలకు ట్రాన్సిటివ్‌గా కనెక్ట్ అవ్వదు మరియు అందువల్ల ఇంటర్-థ్రెడ్ రేస్‌కు కారణం కావచ్చు.
  • వస్తువుతో ఏదైనా పని మరియు ఖరారు() .

స్ట్రీమ్ సర్వీస్:

  • థ్రెడ్ మరియు థ్రెడ్‌లోని ఏదైనా కోడ్‌ను ప్రారంభించడం.
  • థ్రెడ్‌కు సంబంధించిన జీరోయింగ్ వేరియబుల్స్ మరియు థ్రెడ్‌లోని ఏదైనా కోడ్.
  • థ్రెడ్‌లో కోడ్ మరియు జాయిన్() ; థ్రెడ్‌లో కోడ్ మరియు isAlive() == తప్పు .
  • థ్రెడ్‌కు అంతరాయం () మరియు అది ఆగిపోయిందని గుర్తించండి.

పని సూక్ష్మ నైపుణ్యాలకు ముందు జరుగుతుంది

అదే మానిటర్‌ని పొందే ముందు జరిగే-ముందు మానిటర్‌ను విడుదల చేయడం జరుగుతుంది. ఇది విడుదల అని గమనించాలి మరియు నిష్క్రమణ కాదు, అంటే, వేచి ఉండే సమయంలో మీరు భద్రత గురించి ఆందోళన చెందాల్సిన అవసరం లేదు.

మన ఉదాహరణను సరిదిద్దడానికి ఈ జ్ఞానం ఎలా సహాయపడుతుందో చూద్దాం. ఈ సందర్భంలో, ప్రతిదీ చాలా సులభం: బాహ్య తనిఖీని తీసివేసి, సమకాలీకరణను అలాగే వదిలేయండి. ఇప్పుడు రెండవ థ్రెడ్ అన్ని మార్పులను చూడడానికి హామీ ఇవ్వబడింది, ఎందుకంటే ఇతర థ్రెడ్ దానిని విడుదల చేసిన తర్వాత మాత్రమే మానిటర్‌ను పొందుతుంది. మరియు ప్రతిదీ ప్రారంభించబడే వరకు అతను దానిని విడుదల చేయడు కాబట్టి, మేము అన్ని మార్పులను ఒకేసారి చూస్తాము మరియు విడిగా కాదు:

public class Keeper {
    private Data data = null;

    public Data getData() {
        synchronized(this) {
            if(data == null) {
                data = new Data();
            }
        }

        return data;
    }
}

అస్థిర చరరాశికి వ్రాయడం జరుగుతుంది-అదే వేరియబుల్ నుండి చదవడానికి ముందు. మేము చేసిన మార్పు బగ్‌ని సరిచేస్తుంది, అయితే అసలు కోడ్‌ని ఎవరు వ్రాసినా అది ఎక్కడి నుండి వచ్చిందో తిరిగి ఉంచుతుంది - ప్రతిసారీ నిరోధించడం. అస్థిర కీవర్డ్ సేవ్ చేయవచ్చు. వాస్తవానికి, ప్రశ్నలోని ప్రకటన అంటే అస్థిరంగా ప్రకటించబడిన ప్రతిదాన్ని చదివేటప్పుడు, మేము ఎల్లప్పుడూ వాస్తవ విలువను పొందుతాము.

అదనంగా, నేను ఇంతకు ముందు చెప్పినట్లుగా, అస్థిర క్షేత్రాలకు, రాయడం ఎల్లప్పుడూ (దీర్ఘ మరియు రెట్టింపుతో సహా) అణు ఆపరేషన్. మరో ముఖ్యమైన విషయం: మీరు ఇతర ఎంటిటీలకు (ఉదాహరణకు, ఒక శ్రేణి, జాబితా లేదా ఇతర తరగతి) సూచనలను కలిగి ఉన్న అస్థిర ఎంటిటీని కలిగి ఉంటే, ఆ ఎంటిటీకి సంబంధించిన సూచన మాత్రమే ఎల్లప్పుడూ "ఫ్రెష్"గా ఉంటుంది, కానీ ప్రతిదానికీ కాదు అది ఇన్కమింగ్.

కాబట్టి, మా డబుల్-లాకింగ్ రామ్‌లకు తిరిగి వెళ్లండి. అస్థిరతను ఉపయోగించి, మీరు ఈ విధంగా పరిస్థితిని పరిష్కరించవచ్చు:

public class Keeper {
    private volatile Data data = null;

    public Data getData() {
        if(data == null) {
            synchronized(this) {
                if(data == null) {
                    data = new Data();
                }
            }
        }
        return data;
    }
}

ఇక్కడ మనకు ఇప్పటికీ లాక్ ఉంది, కానీ డేటా == శూన్యమైతే మాత్రమే. మేము అస్థిర రీడ్‌ని ఉపయోగించి మిగిలిన కేసులను ఫిల్టర్ చేస్తాము. అస్థిరమైన దుకాణం అస్థిరమైన రీడ్‌కు ముందు జరుగుతుంది మరియు ఫీల్డ్ యొక్క విలువను చదివిన వారికి కన్స్ట్రక్టర్‌లో జరిగే అన్ని కార్యకలాపాలు కనిపిస్తాయి అనే వాస్తవం ద్వారా ఖచ్చితత్వం నిర్ధారించబడుతుంది.