16

How do I modify an int atomically and thread-safely in Java?

Atomically increment, test & set, etc...?

ripper234
  • 222,824
  • 274
  • 634
  • 905

3 Answers3

31

Use AtomicInteger.

Bombe
  • 81,643
  • 20
  • 123
  • 127
  • 2
    Which is fine if all you need is the limited set of operations it provides. The "etc" in the question suggests more flexibility. – skaffman Jul 20 '09 at 08:34
  • 7
    Does it ? If he's looking for more, he should be more explicit. AtomicInteger seems to be the right answer in the meantime – Brian Agnew Jul 20 '09 at 08:35
  • 2
    Also have a look at the other classes in the java.util.concurrent package. They can be helpful for the "etc"-stuff – Roland Schneider Jul 20 '09 at 08:37
1

Thread safety can be achieved via synchronized functions. Wrap your int (or such data) in a class which provides the required functionalities via synchronized methods, e.g.

public class X
{
  protected int x;
  public synchronized void set( int value )
  {
    x = value;
  }
}

You can also use classes from the java.util.concurrent.atomic package, e.g. AtomicInteger or AtomicIntegerArray

Why this answer won't work

I just wanted to be sure to point out exactly what is wrong with this answer, in case anyone thinks that synchronized can be used to solve thread race effects.

| Thread A      | Thread B         | 
|---------------|------------------|
| read x (x=4)  |                  |
|               | read x (x=4)     |
| Calculate 4+1 |                  |
| EAX ← 5       |                  |
|               | Calculate 4+1    |
|               | EAX ← 5          |
| Start sync    |                  |
| {             | Start sync       |
| { x ← 5       |    wait          |
| {             |    wait          |
| End sync      |    wait          |
|               | {                | 
|               | { x ← 5          |
|               | {                | 
|               | End sync         |

The end result of the operations:

x = 4;
x += 1;
x += 1;

is that x = 5 rather than 6.

The same issue exists with the volatile keyword. The volatile keyword doesn't save you from thread effects. The volatile keyword only ensures that

  • caches are flushed before a variable is read
  • caches are flushed after a value is written

Strictly speaking, volatile ensures that memory operations are not reordered around a volatile variable. Which means you still suffer from the:

  • read from x
  • write to x

problem.

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
CsTamas
  • 4,103
  • 5
  • 31
  • 34
  • 3
    Synchronized is pretty heavy weight and wouldn't really serve as an effective replacement for Interlocked. People use Interlocked because it's fast and lightweight. – Deeko Oct 25 '14 at 13:07
0
private final static AtomicInteger at = new AtomicInteger();

public void run() {
    at.set(7);
    int i = at.incrementAndGet();
epox
  • 9,236
  • 1
  • 55
  • 38