0

Suppose I have two threads updating an object, and one thread reading from that object with no synchronization. Obviously, this is run condition. However, I am wondering if the variable itself can only partially written.

public class CommonObject extends Object
{
    static int memberVar=-1;
}

public class Input1Thread extends Thread
{   
    public void run()   
    {
        while(true)
            CommonObject.memberVar = 1
    }
}

public class Input2Thread extends Thread
{   
    public void run()   
    {
        while(true)
            CommonObject.memberVar = 2;
    }
}

public class OutputThread extends Thread
{   
    public void run()   
    {
        while(true)
            System.out.println("CommonObject.memberVar"+ CommonObject.memberVar);
    }
}  

I would assume the value printed out will also be either 2 or 1. However, I was wondering if it was possible that the variable might be halfway set?

I used primitives as an example, but I would like the answer would for objects also, if it is different.

Brian
  • 14,610
  • 7
  • 35
  • 43
GC_
  • 448
  • 4
  • 23
  • I think this question and answer are better. Also they are more specific to word tearing. – GC_ Jan 27 '17 at 22:30

3 Answers3

3

It depends on the type of the variable.

doubles and longs (the two 64-bit types in Java) are allowed to word-tear if they're not volatile, while all other types (including references) may never tear. Word tearing would give you the behavior you're worried about: some of the bytes are from the old value, some of them are from the new value, and the overall result is a value that's neither the old nor new.

This is specified in JLS 17.7:

For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.

Writes and reads of volatile long and double values are always atomic.

Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.

Of course, introducing data races introduces a whole host of issues; but your question was specifically targeted at word tearing, so I'm only addressing that here, except to note that "just because you can, doesn't mean you should." You should be careful to analyze each data race you have and prove that it's benign (as some of them are -- like String.hashCode's caching of its values).

yshavit
  • 42,327
  • 7
  • 87
  • 124
  • Great answer. I think this answer is better than the answer in the other question. – GC_ Feb 29 '16 at 05:48
  • So a long is totally safe if it is volatile? – GC_ Mar 02 '16 at 23:17
  • @GC_ It depends on what you mean by "safe"! It won't word-tear... but data races have other problems, like appearing to happen out of order, or possibly not being seen by other threads at all (if they're cached in a local register). – yshavit Mar 02 '16 at 23:40
  • Wait, scratch that -- I had a brain fart, and mentally switched from thinking you were asking about volatile to non-volatiles halfway through my comment. Yes, longs are totally safe if they're volatile. :) (Though of course, if you need to update them along with other state in an atomic way, then volatile isn't enough.) – yshavit Mar 02 '16 at 23:43
0

Checkout the AtomicInteger class and the java tutorial on threads for examples. Also the javadoc.

https://docs.oracle.com/javase/tutorial/essential/concurrency/

Bob
  • 780
  • 9
  • 10
-1

It's safe for primitives but not safe for Objects.for example,Object A has two variables int a,b,if you try to change their values in two different threads,you will find that values from both thread may appear at the same time sometimes .

wngxao
  • 72
  • 5
  • Objects are not variables. The question was specifically about variables. Also, it's not safe for _all_ primitive types. The JLS explicitly allows updates of `double` variables and `long` variables to be non-atomic. (See yshavit's answer) – Solomon Slow Feb 29 '16 at 14:54