नीचे एक छोटी सी जावा कार्यक्रम है। इसमें "सीएनटी" नामक एक काउंटर है जिसे बढ़ाया जाता है और फिर "मॉनिटर" नामक एक सूची में जोड़ा जाता है। "cnt" को कई धागे से बढ़ाया जाता है, और मान कई थ्रेड द्वारा "मॉनिटर" में जोड़े जाते हैं।कन्करेंसी ब्लॉक सिंक्रनाइज़ का उपयोग कर अपेक्षित परिणाम देने नहीं
विधि के अंत में "जाने()", cnt और monitor.size() एक ही मूल्य है चाहिए, लेकिन वे नहीं है। monitor.size() में सही मान है।
आप टिप्पणी की सिंक्रनाइज़ ब्लॉकों में से एक uncommenting, और बाहर टिप्पणी वर्तमान में uncommented एक के बाद कोड को बदलते हैं, कोड अपेक्षित परिणाम पैदा करता है। साथ ही, यदि आप थ्रेड गिनती (THREAD_COUNT) को 1 पर सेट करते हैं, तो कोड अपेक्षित परिणाम उत्पन्न करता है।
यह केवल कई वास्तविक कोर के साथ एक मशीन पर पुनः प्रस्तुत किया जा सकता है।
public class ThreadTester {
private List<Integer> monitor = new ArrayList<Integer>();
private Integer cnt = 0;
private static final int NUM_EVENTS = 2313;
private final int THREAD_COUNT = 13;
public ThreadTester() {
}
public void go() {
Runnable r = new Runnable() {
@Override
public void run() {
for (int ii=0; ii<NUM_EVENTS; ++ii) {
synchronized(monitor) {
synchronized(cnt) { // <-- is this synchronized necessary?
monitor.add(cnt);
}
// synchronized(cnt) {
// cnt++; // <-- why does moving the synchronized block to here result in the correct value for cnt?
// }
}
synchronized(cnt) {
cnt++; // <-- why does moving the synchronized block here result in cnt being wrong?
}
}
// synchronized(cnt) {
// cnt += NUM_EVENTS; // <-- moving the synchronized block here results in the correct value for cnt, no surprise
// }
}
};
Thread[] threads = new Thread[THREAD_COUNT];
for (int ii=0; ii<THREAD_COUNT; ++ii) {
threads[ii] = new Thread(r);
}
for (int ii=0; ii<THREAD_COUNT; ++ii) {
threads[ii].start();
}
for (int ii=0; ii<THREAD_COUNT; ++ii) {
try { threads[ii].join(); } catch (InterruptedException e) { }
}
System.out.println("Both values should be: " + NUM_EVENTS*THREAD_COUNT);
synchronized (monitor) {
System.out.println("monitor.size() " + monitor.size());
}
synchronized (cnt) {
System.out.println("cnt " + cnt);
}
}
public static void main(String[] args) {
ThreadTester t = new ThreadTester();
t.go();
System.out.println("DONE");
}
}
आपका अवलोकन वास्तव में क्या हो रहा है यह है: इंटीजर tmp = नया इंटीजर (सीएनटी + 1); वह हिस्सा था जिसे मैं याद कर रहा था। मैं इस बात पर विचार करना भूल गया कि इसमें अपरिवर्तनीयता और ऑटोबॉक्सिंग कैसे खेलती है। – mangotang