क्या हमें निजी फ़ील्ड को volatile
के रूप में घोषित करना चाहिए यदि इंस्टेंट का उपयोग एकाधिक थ्रेड में किया जाता है?जावा: गेटर्स और सेटर्स के साथ 'अस्थिर' निजी फ़ील्ड
import java.util.concurrent.TimeUnit;
// Broken! - How long would you expect this program to run?
public class StopThread {
private static boolean stopRequested; // works, if volatile is here
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while (!stopRequested)
i++;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
स्पष्टीकरण का कहना है कि
while(!stopRequested)
i++;
कुछ इस तरह के लिए अनुकूलित है:
if(!stopRequested)
while(true)
i++;
Effective Java में, वहाँ एक उदाहरण है जहां कोड अस्थिर बिना काम नहीं करता है
तो stopRequested
के और संशोधनों को नहीं देखा गया है पृष्ठभूमि धागे से, तो यह हमेशा के लिए loops। (Btw, कि कोड JRE7 पर volatile
बिना समाप्त हो जाता है।)
अब इस वर्ग पर विचार करें: इस प्रकार
public class Bean {
private boolean field = true;
public boolean getField() {
return field;
}
public void setField(boolean value) {
field = value;
}
}
और एक धागा:
public class Worker implements Runnable {
private Bean b;
public Worker(Bean b) {
this.b = b;
}
@Override
public void run() {
while(b.getField()) {
System.err.println("Waiting...");
try { Thread.sleep(1000); }
catch(InterruptedException ie) { return; }
}
}
}
ऊपर कोड के रूप में वाष्पशील का उपयोग किए बिना की उम्मीद काम करता है :
public class VolatileTest {
public static void main(String [] args) throws Exception {
Bean b = new Bean();
Thread t = new Thread(new Worker(b));
t.start();
Thread.sleep(3000);
b.setField(false); // stops the child thread
System.err.println("Waiting the child thread to quit");
t.join();
// if the code gets, here the child thread is stopped
// and it really gets, with JRE7, 6 with -server, -client
}
}
मुझे लगता है कि सार्वजनिक सेटटर के कारण, सी ompiler/JVM को कभी भी कोड को अनुकूलित नहीं करना चाहिए जो getField()
पर कॉल करता है, लेकिन this article कहता है कि कुछ "अस्थिर बीन" पैटर्न (पैटर्न # 4) है, जिसे उत्परिवर्तनीय थ्रेड-सुरक्षित कक्षाएं बनाने के लिए लागू किया जाना चाहिए। अद्यतन: शायद यह आलेख केवल आईबीएम जेवीएम के लिए लागू होता है?
सवाल यह है कि: जेएलएस का कौन सा हिस्सा स्पष्ट रूप से या स्पष्ट रूप से कहता है कि सार्वजनिक गेटर्स/सेटर्स के साथ निजी आदिम फ़ील्ड volatile
(या उन्हें नहीं) के रूप में घोषित किया जाना चाहिए?
लंबे प्रश्न के लिए खेद है, मैंने विवरण में समस्या की व्याख्या करने की कोशिश की। अगर कुछ स्पष्ट नहीं है तो मुझे बताएं। धन्यवाद।
ऐसा नहीं है कि आपको थ्रेड को रद्द करने के लिए उस फ़ील्ड की आवश्यकता है, तो आप थ्रेड पर बाधित ध्वज का उपयोग कर सकते हैं। –
@NathanHughes, ये कक्षाएं केवल न्यूनतम उदाहरण हैं, वास्तविक कोड अलग है, वहां कोई थ्रेड बाधा नहीं है। – khachik