40

Are the primitive data types like int & short thread-safe in Java? I have executed the following code and couldn't see expected result 500 some times.

public class SampleThree extends Thread
{
    static long wakeUpTime = System.currentTimeMillis() + (1000*20);
    static int inT;
    public static void main(String args[])
    {
        System.out.println("initial:" + inT);
        for(int i=0; i<500; i++)
            new SampleThree().start();
        try {
            Thread.sleep(wakeUpTime - System.currentTimeMillis() + (1000*30));
            System.out.println("o/p:" + inT);
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }

    public void run()
    {
        try {
            long s = wakeUpTime - System.currentTimeMillis();
            System.out.println("will sleep ms: " + s);
            Thread.sleep(s);
            inT++; // System.out.println(inT);
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}

Here concurrently 500 thread will update the int variable inT. Main thread after waiting for concurrent update to be completed, prints inT value.

Find similar example here

krishna
  • 807
  • 2
  • 11
  • 19
  • 9
    No, they are not thread safe. If you only plan on reading, you should consider making the member `volatile`. If you plan to read and write to it from different threads, you should make it `synchronized` – Guillaume Polet Feb 14 '12 at 14:41

4 Answers4

68

There are three ways in which they're not safe:

  • long and double aren't even guaranteed to be updated atomically (you could see half of a write from a different thread)
  • The memory model doesn't guarantee that you'll see the latest updates from one thread in another thread, without extra memory barriers of some kind
  • The act of incrementing a variable isn't atomic anyway

Use AtomicInteger etc for thread-safe operations.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
10

Primitive types are not thread safe. Check this tutorial.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
Parvin Gasimzade
  • 25,180
  • 8
  • 56
  • 83
  • 1
    The key point is that if a primitive were defined as part of an instance of an object, that primitive would be on the heap, and not thread safe. – petertc Feb 09 '15 at 13:56
  • 3
    That's weird. The oracle documentation actually says primitive type access is atomic for int: https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html – Yamcha May 22 '17 at 14:47
  • 1
    @Parvin, Except for long and double, primitive types are guaranteed to be atomic. If you're reading or writing the value, its thread safe for that one operation. – Pacerier Sep 20 '17 at 02:39
  • Link in answer is dead - *"Hmmm… can't reach this page | ERR_CONNECTION_TIMED_OUT"*. – Pang Aug 14 '23 at 02:58
4

I would suggest using classes in java.util.concurrent.atomic. They are designed for thread-safety and in some cases the JVM can take advantage of hardware features to optimize.

Jeff Miller
  • 1,424
  • 1
  • 10
  • 19
0
  1. To read/write of a value in a multiple thread environment, the program should have proper synchronize or lock to prevent data races. It has nothing to do with which data type to access. In an ideal world, we should share nothing or only share immutable objects, which is always thread safe.

  2. In theory, It is even not ensured to be atomic for long/double according to https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.7 HOWEVER, the implementation tends to atomic, the following code print out nothing with or without volatile keyword in my environment(64bit ubuntu 18.04, Intel 64bit CPU, Oracle JDK 8), so it is atomic in this situation, which I guess apply to all Intel/AMD 64 CPU. We could do the same for double as well, although it is a little tricky to construct double value with certain property to check.

public class LongThreadSafe {

    // multiple threads read and write this value.
    // according to the java spec, only volatile long is guaranteed to be atomic
    private static long value = 0;

    private static final int max = (1 << 30) - 1;
    private static final int threadCount = 4;
    static ExecutorService executorService = Executors.newFixedThreadPool(threadCount);

    static CyclicBarrier barrier = new CyclicBarrier(threadCount);

    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < threadCount; i++) {
            executorService.submit(() -> {
                try {
                    // all threads start to work at the same time
                    barrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }

                for (int j = 1; j < max; j++) {
                    // read value into v2
                    long v2 = value;
                    // check v2 
                    int low = (int) v2;
                    int high = (int) (v2 >> 32);
                    if ((high << 1) != low) {
                        System.out.println("invalid number found high=" + high + ", low=" + low);
                    }
                    // write LongThreadSafe.value again 
                    LongThreadSafe.value = ((long) j << 32) | (long) (j << 1);


                }
            });
        }
        executorService.shutdown();
        executorService.awaitTermination(10, TimeUnit.MINUTES);
    }
}
Jacky_Cai
  • 81
  • 1
  • 2
  • Welcome to finally *posting* on stackoverflow. Please elaborate on the `It` starting your post: the question's code shows concurrent writes just for `inT`, which is neither `double` nor `long`. – greybeard Dec 07 '19 at 04:58
  • LongThreadSafe.value is the value been written and read by multiple threads. already enclose code with ~~~, thx – Jacky_Cai Dec 08 '19 at 01:36
  • It still isn't clear what the `It` starting your post is referring to: the one explicit question from [the question](https://stackoverflow.com/q/9278764/3789665) asks about `types` - to refer to those types, it would have to be *They*. – greybeard Dec 08 '19 at 04:24
  • You are right, I updated the answer to cover thread safe and types – Jacky_Cai Dec 09 '19 at 10:04