问题描述:

Given:

public class TestSeven extends Thread {

private static int x;

public synchronized void doThings() {

int current = x;

current++;

x = current;

}

public void run() {

doThings();

}

}

Which statement is true?

A. Compilation fails.

B. An exception is thrown at runtime.

C. Synchronizing the run() method would make the class thread-safe.

D. The data in variable "x" are protected from concurrent access problems.

E. Declaring the doThings() method as static would make the class thread-safe.

F. Wrapping the statements within doThings() in a synchronized(new Object()) { } block would make the class thread-safe.

isn't it enough to mark doThings() as synchronized in order to make that class Thread-safe ? i see that the correct answer is D but the Model answer of this question is E, But i don't understand why?

网友答案:

E. Declaring the doThings() method as static would make the class thread-safe.

That is kind of a tricky answer. The method is already synchronized, but on the instance, whereas the state is in a static field, i.e. on the class. Making it static synchronized is indeed the correct answer, because then it synchronizes on the class, not on a (meaningless) instance.

D. The data in variable "x" are protected from concurrent access problems.

private static int x;

This is a static variable. It is shared by all instances of the class, so synchronizing on individual instances is not helpful, in the same way as F would not be helpful, which synchronizes on a complete throw-away dummy object.

网友答案:

According to the language spec:

A synchronized method acquires a monitor (§17.1) before it executes.

For a class (static) method, the monitor associated with the Class object for the method's class is used.

For an instance method, the monitor associated with this (the object for which the method was invoked) is used.

This means that in the code you provided the synchronized keyword causes the method to acquire a lock on this before executing the body of the method. However, since x is static that doesn't ensure that the update to x will be atomic. (Another instance of the class could enter the synchronized region and do an update at the same time since they have different this values and thus different locks.)

However, declaring doStuff static will make all calls to the method acquire the same lock (the one on the Class) and thus would ensure mutual exclusion in the method body.

The specifications is really spelling out that:

class A {
    static synchronized void doSomething() {
        // ...
    }
}

is literally the same thing as

class A {
    static void doSomething() {
        synchronized(A.class) {
            // ...
        }
    }
}

Similarly:

class B {
    synchronized void doSomething() {
        // ...
    }
}

is literally the same thing as

class B {
    void doSomething() {
        synchronized (this) {
            // ...
        }
    }
}
网友答案:

By way of synchronizing the doThings() method, you are holding the lock for a particular TestSeven object. However, static variables of the class does not belong to the specific instance of the object itself. They belong to the Class object TestSeven.class. So, either you could go for a

synchronized (TestSeven.class){
    int current = x;
    current++;
    x = current;
}

inside your doThings() method which is acquiring the Class lock inside an instance lock which is overdoing things. So, you could mark the method as static so that you end up acquiring the lock of the Class object alone.

网友答案:

Since x is static other threads could modify it at the same time doThings method is running. Making doThings static will stop this.

网友答案:

I agree with you that the correct answer is D. I would say that E is incorrect because if I set doThings() as static and remove the synchronized keyword, I could just start up 50 TestSeven threads and it could result in incorrect x value.

Note: I was wrong here, I missed the point that synchronized method without static actually use the instance as the lock monitor instead of the Class itself.

相关阅读:
Top