Search code examples
javasynchronizationimmutabilityvolatile

Doubts related to volatile , immutable objects, and their use to achieve synchronization


I was reading book "java concurrency in practice" and end up with some doubts after few pages.

1) Voltile with non premitive data types : private volatile Student s; what is significance of volatile when it comes with non premitive data types ? (I think in this case only think that is sure to be visible to all threads is what Strudent object s is pointing currently and it is possible one thread A modifies some internal member of student and that is not visible to other threads. Am I right ??)

2) Is a variable can be immutable , even if internal members are not declared as final ?? For example :

Class  A {

    private Set<String> s = new Set();
    public A() {
        s.add("Moe");
        s.add("Larry");
        s.add("Curly");
    }
} 

In this class do we need to make Set s final to make it immutable or this class is still immutable ? (because even in this case we can't change state of object after it is created).

3 ) There is one example in book that shows how to use volatile and immutable class in combination to get synchronization. Before I put that question I have one more doubt. suppose there is some function like this :

private Student s = new Student;

void func() {
    s.func2();      // 1
    if(s.isPossible()) { //2
        s = new Student(); //3      
    }
}

a)func2() acess internal members of s. Now consider Thread A entered into func2 after executing line 1 and Thread B same time reassign s with new object. When Thread A resumes what it will use new object or the old one ? ( suppose s initally points to memory location 100 (old object) and after a new object is assigned it started pointing to 200 (new object) then when Thread A resumes it will acess address 100 or address 200).

b) If I make s volatile , will it make any difference to above case.

4.) And here is last one

@Immutable
class OneValueCache {
    private final BigInteger lastNumber;
    private final BigInteger[] lastFactors;
    public OneValueCache(BigInteger i,
    BigInteger[] factors) {
        lastNumber = i;
        lastFactors = Arrays.copyOf(factors, factors.length);
    }
    public BigInteger[] getFactors(BigInteger i) {
        if (lastNumber == null || !lastNumber.equals(i))
            return null;
        else
            return Arrays.copyOf(lastFactors, lastFactors.length);
    }
}

@ThreadSafe
public class VolatileCachedFactorizer implements Servlet {
    private volatile OneValueCache cache = new OneValueCache(null, null);
    public void service(ServletRequest req, ServletResponse resp) {
        BigInteger i = extractFromRequest(req);
        BigInteger[] factors = cache.getFactors(i); // Position A

        if (factors == null) {
            factors = factor(i);
            cache = new OneValueCache(i, factors); // Position B
        }
        encodeIntoResponse(resp, factors);
    }
}

Accroding to book class "VolatileCachedFactorizer" is thread safe. Here is my reasoning why it is thread safe (Correct me if I am wrong.) Positin A and Position B are doubtful positions.

Position A : As cache is pointing to immutable object , any function call is safe (right ?).

Position B : It can have two issue

a)Threads see cache improperly initialized . Not possible in this case as immutable object are guaranteed to be properly initialized (right ?).

b)New assigned object not visible to other threads. Not possible is this case as cache is volatile (right ?).

But it is possible thread A call getFactors() and other thread B reassign cache , in this case A will continue to see old object (right ?)


Solution

  • Found out after some testing all my answers.

    1. volatile only applies to reference. Any object point by volatile object need not to be visible other threads.

    2. Yes final is important. Without it object of class will not be immutable.

    3. Suppose a variable "obj" is pointing to location x(where the actual object is placed) when a function call on obj is started then during function call all member variables will be read from location x even if some other thread assign a different object on "obj".

    4. Assumed explanations for all answers are correct.