Avoiding lost Java updates without using synchronization directly

I am wondering if the lost update problem can be avoided when multiple threads update the same date, while avoiding the use of synchronized(x) { } .

I will do many additions and increments:

 val++; ary[x] += y; ary[z]++; 

I don’t know how Java compiles them into byte code, and if the thread can be interrupted in the middle of one of these blocks of byte code statements. In other words, are these claims thread safe?

Also, I know that the Vector class is in sync, but I'm not sure what that means. Will the following code be a safe thread, since the value at position i will not change between vec.get(i) and vec.set(...) .

 class myClass { Vector<Integer> vec = new Vector<>(Integer); public void someMethod() { for (int i=0; i < vec.size(); i++) vec.set(i, vec.get(i) + value); } } 

Thanks in advance.

+4
source share
2 answers

For the purpose of threading, ++ and += treated as two operations (four for double and long ). In this way, updates can be compressed with each other. Not only one, but the scheduler, acting at the wrong time, can destroy the milliseconds of updates.

java.util.concurrent.atomic is your friend.

Your code can be made safe if you do not mind every element that is updated individually, and you do not change the size (!), Like:

 for (int i=0; i < vec.size(); i++) { synchronized (vec) { vec.set(i, vec.get(i) + value); } } 

If you want to add size to Vector , you need to move the synchronized statement outside the for loop, and you can just use a simple new ArrayList . For a synchronized list there is actually not much use.

But you can use AtomicIntegerArray :

 private final AtomicIntegerArray ints = new AtomicIntegerArray(KNOWN_SIZE); [...] int len = ints.length(); for (int i=0; i<len; ++i) { ints.addAndGet(i, value); } } 

This has the advantage of no locks (!) And no boxing. The implementation is also quite interesting, and you will need to understand that it makes a more complex update (random number generators, for example).

+6
source

vec.set () and vec.get () are thread safe because they will not set and retrieve values ​​in such a way as to lose sets and receive in other threads. It does not mean that your set and your get will be executed without interruption.

If you are really going to write code, as in the examples above, you should probably block something. And synchronized(vec) { } no worse than any. You are requesting that two operations be performed in synchronization, and not just one operation with a thread.

Even java.util.concurrent.atomic will guarantee that one operation (getting or installing) will happen safely. You need to get-and-increment in one operation.

+1
source

All Articles