"హలో, అమిగో! అనేక థ్రెడ్‌లు ఏకకాలంలో భాగస్వామ్య వనరును యాక్సెస్ చేయడానికి ప్రయత్నించినప్పుడు తలెత్తే సమస్యల గురించి ఎల్లీ మీకు చెప్పినట్లు మీకు గుర్తుంది, అవునా?"

"అవును."

"విషయం అంతా కాదు. ఇంకో చిన్న సమస్య ఉంది."

మీకు తెలిసినట్లుగా, కంప్యూటర్‌లో డేటా మరియు కమాండ్‌లు (కోడ్) నిల్వ చేయబడే మెమరీ ఉంటుంది, అలాగే ఈ ఆదేశాలను అమలు చేసే ప్రాసెసర్ మరియు డేటాతో పని చేస్తుంది. ప్రాసెసర్ మెమరీ నుండి డేటాను చదువుతుంది, దానిని మారుస్తుంది మరియు మెమరీకి తిరిగి వ్రాస్తుంది. గణనలను వేగవంతం చేయడానికి, ప్రాసెసర్ దాని స్వంత అంతర్నిర్మిత "ఫాస్ట్" మెమరీని కలిగి ఉంది: కాష్.

ప్రాసెసర్ చాలా తరచుగా ఉపయోగించే వేరియబుల్స్ మరియు మెమరీ ప్రాంతాలను దాని కాష్‌కి కాపీ చేయడం ద్వారా వేగంగా పని చేస్తుంది. అప్పుడు అది ఈ ఫాస్ట్ మెమరీలో అన్ని మార్పులను చేస్తుంది. ఆపై అది డేటాను తిరిగి "స్లో" మెమరీకి కాపీ చేస్తుంది. ఈ సమయంలో, స్లో మెమరీలో పాత (మారదు!) వేరియబుల్స్ ఉంటాయి.

ఇక్కడే సమస్య తలెత్తుతోంది. ఒక థ్రెడ్ పై ఉదాహరణలో isCancel లేదా isInterrupted వంటి వేరియబుల్‌ను మారుస్తుంది , కానీ రెండవ థ్రెడ్ «ఈ మార్పును చూడలేదు , ఎందుకంటే ఇది ఫాస్ట్ మెమరీలో జరిగింది. థ్రెడ్‌లు ఒకదానికొకటి కాష్‌కి యాక్సెస్‌ను కలిగి ఉండకపోవడమే దీనికి పరిణామం. (ప్రాసెసర్ తరచుగా అనేక స్వతంత్ర కోర్లను కలిగి ఉంటుంది మరియు థ్రెడ్‌లు భౌతికంగా భిన్నమైన కోర్‌లపై నడుస్తాయి.)

నిన్నటి ఉదాహరణను గుర్తుచేసుకుందాం:

కోడ్ వివరణ
class Clock implements Runnable
{
private boolean isCancel = false;

public void cancel()
{
this.isCancel = true;
}

public void run()
{
while (!this.isCancel)
{
Thread.sleep(1000);
System.out.println("Tick");
}
}
}
ఇతర థ్రెడ్‌లు ఉన్నాయని థ్రెడ్‌కు «తెలియదు».

రన్ పద్ధతిలో, isCancel వేరియబుల్ మొదటిసారి ఉపయోగించినప్పుడు చైల్డ్ థ్రెడ్ కాష్‌లో ఉంచబడుతుంది. ఈ ఆపరేషన్ కింది కోడ్‌కి సమానం:

public void run()
{
boolean isCancelCached = this.isCancel;
while (!isCancelCached)
{
Thread.sleep(1000);
System.out.println("Tick");
}
}

మరొక థ్రెడ్ నుండి రద్దు పద్ధతిని కాల్ చేయడం వలన సాధారణ (నెమ్మదిగా) మెమరీలో isCancel విలువ మారుతుంది , కానీ ఇతర థ్రెడ్‌ల కాష్‌లలో కాదు.

public static void main(String[] args)
{
Clock clock = new Clock();
Thread clockThread = new Thread(clock);
clockThread.start();

Thread.sleep(10000);
clock.cancel();
}

"ఓహో! మరియు వారు సింక్రొనైజ్డ్ లాగా దీనికి కూడా ఒక అందమైన పరిష్కారాన్ని కనుగొన్నారా  ?"

"మీరు నమ్మరు!"

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

అస్థిర కీవర్డ్ పుట్టింది . మేము ఈ కీవర్డ్‌ని వేరియబుల్ డిక్లరేషన్‌కి ముందు ఉంచాము, దాని విలువను కాష్‌లో ఉంచకూడదు. మరింత ఖచ్చితంగా చెప్పాలంటే, ఇది కాష్‌లో ఉంచబడలేదని కాదు, ఇది ఎల్లప్పుడూ సాధారణ (నెమ్మదిగా) మెమరీ నుండి చదవాలి మరియు వ్రాయాలి.

మా పరిష్కారాన్ని ఎలా పరిష్కరించాలో ఇక్కడ ఉంది, కాబట్టి ప్రతిదీ సరిగ్గా పని చేస్తుంది:

కోడ్ వివరణ
class Clock implements Runnable
{
private volatile boolean isCancel = false;

public void cancel()
{
this.isCancel = true;
}

public void run()
{
while (!this.isCancel)
{
Thread.sleep(1000);
System.out.println("Tick");
}
}
}
అస్థిర మాడిఫైయర్ అన్ని థ్రెడ్‌ల ద్వారా భాగస్వామ్యం చేయబడిన సాధారణ మెమరీ నుండి ఎల్లప్పుడూ చదవబడుతుంది మరియు వ్రాయబడుతుంది.
public static void main(String[] args)
{
Clock clock = new Clock();
Thread clockThread = new Thread(clock);
clockThread.start();

Thread.sleep(10000);
clock.cancel();
}

"అంతే?"

"అంతే. సింపుల్ అండ్ బ్యూటిఫుల్."