1

I know that i++ is not a thread safe operation. I also understand why i++ is faster than i = i+1 also. Is i = i+1 any different from i++ in terms of thread safety? Any bytecode level explanation would be really helpful.

karmanaut
  • 628
  • 1
  • 6
  • 17
  • 7
    They compile to [identical bytecode](http://pastebin.com/raw.php?i=G6Hadz8Q), so they should have the same performance. – August Dec 02 '14 at 04:03
  • 1
    @August2 - Nice. You should post that as an answer. – EJK Dec 02 '14 at 04:05

4 Answers4

9

Neither i += 1 nor i++ is atomic (neither is thread safe). The same goes for ++i. Here's a simple test you can run to prove this:

public class Test {

    static volatile int x, y;

     static class IncThread extends Thread {
         public void run() {
            for (int i=0; i<50000; i++) x++;
            for (int i=0; i<50000; i++) y = y+1;
         }
     }

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new IncThread();
        Thread t2 = new IncThread();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.printf("x = %d, y = %d%n", x, y);
    }

}

Here's what I get for output:

x = 99897, y = 81556

Obviously, some of the writes got lost. There's a nice little blog post, ++ not considered atomic, that explains this. That post also points out that @August's answer is misleading. That bytecode (iinc) is only generated for incrementing local variables, which are not interesting from the perspective of thread-safety. (The blog post also talks about the different bytecodes used for increments.)

DaoWen
  • 32,589
  • 6
  • 74
  • 101
  • If you have an issue with August's answer, you should put a comment under that answer, and possibly a downvote. Someone might use that answer, and not even see yours. – Dawood ibn Kareem Dec 02 '14 at 04:35
6

There is no difference between i++ and i += 1, bytecode-wise:

Increment (Source):

public static void main(String[] args) {
    int i = 0;
    i++;
}

Increment (Bytecode):

public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iinc          1, 1
       5: return

Compound addition (Source):

public static void main(String[] args) {
    int i = 0;
    i += 1;
}

Compound addition (Bytecode):

public static void main(java.lang.String[]);
    Code:
       0: iconst_0      
       1: istore_1      
       2: iinc          1, 1
       5: return 

The bytecode used for incrementing fields is also the same, although it doesn't use the iinc instruction (because it would need a local variable index):

int x;

void inc() { x++; }
void assign() { x += 1; }

void inc();
    Code:
       0: aload_0       
       1: dup           
       2: getfield      #2                  // Field x:I
       5: iconst_1      
       6: iadd          
       7: putfield      #2                  // Field x:I
      10: return        

  void assign();
    Code:
       0: aload_0       
       1: dup           
       2: getfield      #2                  // Field x:I
       5: iconst_1      
       6: iadd          
       7: putfield      #2                  // Field x:I
      10: return    
August
  • 12,410
  • 3
  • 35
  • 51
  • How do you go about reading the bytecode from a compiled source? – David.Jones Dec 02 '14 at 04:16
  • 2
    @DavidJones You can use `javap -c Foo.class` (or my rather crappy [website](http://bytes.i-i.im/)) – August Dec 02 '14 at 04:18
  • You should edit your answer to point out that the `iinc` instruction is only generated to increment _local_ variables. See [++ not considered atomic](http://madbean.com/2003/mb2003-44/) for some examples. – DaoWen Dec 02 '14 at 04:40
1

i=i+1 uses a binary operator (+) which loads the value of i, and adds one to it, and then store the result back to i. In contrast, i++ uses the unary (++) operator which simply increments the value using a single assembly instruction, so in theory it could be more efficient. However, with today's compilers optimization i=i+1 and i++ will result in the same optimized code.

Kalenda
  • 1,847
  • 14
  • 15
-1

There is no differences between i++ and i=i+1 in those terms.

Carlos Espinoza
  • 1,115
  • 11
  • 13