As a matter of fact, the Java memory model is such that a modification
to a variable in one thread may not immediately be visible to other threads. Actually, it
may never be visible. Consider the code in Listing 5–11: if one thread calls
MyClass.loop(), and at some point in the future another thread calls
Myclass.setValue(100), the first thread may still not terminate; may carry on looping
forever and always print out a value other than 100, simply because of the Java
language’s memory model.
Listing 5–11. Java Memory Model Impact
public class MyClass {
private static final String TAG = "MyClass";
private static int mValue = 0;
public static void setValue(int n) {
mValue = n;
}
public static void loop () {
while (mValue != 100) {
try {
Log.i(TAG, “Value is ” + mValue);
Thread.sleep(1000);
} catch (Exception e) {
// ignored
}
}
}
}
You have two options to fix that:
Use the synchronized keyword, as shown in Listing 5–12.
Use the volatile keyword, as shown in Listing 5–13.
Listing 5–12. Adding the Synchronized Keyword
public class MyClass {
private static final String TAG = "MyClass";
private static int mValue = 0;
public static synchronized void setValue(int n) {
mValue = n;
}
public static synchronized int getValue() {
return mValue;
}
public static void loop () {
int value;
while ((value = getValue()) != 100) {
try {
Log.i(TAG, “Value is ” + value);
Thread.sleep(1000);
} catch (Exception e) {
// ignored
}
}
}
}
Listing 5–13. Adding the Volatile Keyword
public class MyClass {
private static final String TAG = "MyClass";
private static volatile int mValue = 0; // we add the volatile keyword and remove
the synchronize keyword
public static void setValue(int n) {
mValue = n; // you’d still have to use synchronized if that statement were mValue += n (not atomic)
}
public static void loop () {
while (mValue != 100) {
try {
Log.i(TAG, “Value is ” + mValue);
Thread.sleep(1000);
} catch (Exception e) {
// ignored
}
}
}
}
沒有留言:
張貼留言