"ஹலோ, அமிகோ! பல இழைகள் ஒரே நேரத்தில் பகிரப்பட்ட ஆதாரத்தை அணுக முயலும்போது ஏற்படும் பிரச்சனைகளைப் பற்றி எல்லி உங்களிடம் கூறியது உங்களுக்கு நினைவிருக்கிறது, ஆம்?"

"ஆம்."

"விஷயம் அதெல்லாம் இல்லை. இன்னொரு சின்ன பிரச்சனையும் இருக்கு."

உங்களுக்குத் தெரியும், ஒரு கணினியில் தரவு மற்றும் கட்டளைகள் (குறியீடு) சேமிக்கப்படும் நினைவகம் உள்ளது, அத்துடன் இந்த கட்டளைகளை இயக்கும் மற்றும் தரவுகளுடன் செயல்படும் செயலி. செயலி நினைவகத்திலிருந்து தரவைப் படித்து, அதை மாற்றி, அதை மீண்டும் நினைவகத்திற்கு எழுதுகிறது. கணக்கீடுகளை விரைவுபடுத்த, செயலி அதன் சொந்த உள்ளமைக்கப்பட்ட "வேகமான" நினைவகத்தைக் கொண்டுள்ளது: கேச்.

அடிக்கடி பயன்படுத்தப்படும் மாறிகள் மற்றும் நினைவகத்தின் பகுதிகளை அதன் தற்காலிக சேமிப்பில் நகலெடுப்பதன் மூலம் செயலி வேகமாக இயங்குகிறது. பின்னர் அது இந்த வேகமான நினைவகத்தில் அனைத்து மாற்றங்களையும் செய்கிறது. பின்னர் அது தரவை மீண்டும் "மெதுவான" நினைவகத்திற்கு நகலெடுக்கிறது. இந்த நேரத்தில், மெதுவான நினைவகத்தில் பழைய (மாறாத!) மாறிகள் உள்ளன.

இங்குதான் பிரச்சினை எழுகிறது. மேலே உள்ள எடுத்துக்காட்டில் 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();
}

"அவ்வளவுதான்?"

"அதுதான். சிம்பிள் அண்ட் ப்யூட்டிவ்."