AtomicInteger or LongAccumulator - java

Can someone tell if LongAccumulator could be a better alternative for AtomicInteger in the below example?
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class IncrementThread implements Runnable{
AtomicInteger atomicint = new AtomicInteger();
public IncrementThread(AtomicInteger atominint) {
this.atomicint = atominint;
}
#Override
public void run() {
while(true)
if(atomicint.incrementAndGet()==4){doSomething(); atomicint.set(0);}
}
private void doSomething() {
System.out.println(Thread.currentThread().getName() + " : counter reached to 4");
}
public static void main(String[] args) {
AtomicInteger atomicint = new AtomicInteger();
IncrementThread incThread1 = new IncrementThread(atomicint);
IncrementThread incThread2 = new IncrementThread(atomicint);
IncrementThread incThread3 = new IncrementThread(atomicint);
ExecutorService threadPool = Executors.newCachedThreadPool();
threadPool.execute(incThread1);
threadPool.execute(incThread2);
threadPool.execute(incThread3);
}
}

In this very exact example (which really does nothing useful) both classes seem to be equivalent.
With LongAccumulator you could pass the whole if statement as a lambda expression. But: The java doc of LongAccumulator states that the supplied function should be side effect free which is not fulfilled (doSomething writes to system out).

I suppose that you would probably use LongAccumulator in the same manner as AtomicInteger in this example. In that case the answer is no.
LongAccumulator accumulate values and count the result only, when you call methods like get(). You also make clearing similar LongAccumulator.reset() method, when it would be has 4 value. But all of this methods in LongAccumulator are not thread safe and you could get unpredictable results, because you use multiple threads for reading and updating.
LongAccumulator is good, when you know that many different threads will be update value, but the reading is seldom and more over, you should be sure that reading or reset happen only in one thread, if you matter about synchronization.
But if you don't, LongAccumulator could be better. For example, when you want to count statistic, because if you want get statistic you more probably don't mean "statistic exactly in time of calling", you mean something like "current" results.
This reasoning is applicable for LongAdder too.
In your example there are two possible improvements.
First, you can use:
while(true)
if(atomicint.incrementAndGet()==4){doSomething(); atomicint.compareAndSet(4, 0);}
Now you check, that you reset the same state of atomicint variable.
Another possible improvement - don't use AtomicLong or LongAccumulator, just use simple long variable with volatile keyword. It will be simpler and more applicable here, because in this example you don't use capabilities (like I mention in first improvement).
You could know more in documentation and classes' sources
LongAdder
LongAccumulator
About volatile
Most efficient - sources :)

Related

Java Concurrency volatile for reading synchronization for writing

I need to create a class that has a shared-between-threads Object (lets call is SharedObject). The special thing about SharedObject is that it holds a String that will be returned in multithreaded environment, and sometimes the entire SharedObject will be written to by changing field reference to newly created object.
I do not want to make the read and write both synchronised on the same monitor because the write scenario is happening rarely while read scenario is quite common. Therefore I did the following:
public class ObjectHolder {
private volatile SharedObject sharedObject;
public String getSharedObjectString() {
if (!isObjectStillValid()) {
obtainNewSharedObject()
}
return sharedObject.getCommonString()
}
public synchronized void obtainNewSharedObject() {
/* This is in case multiple threads wait on this lock,
after first one obtains new object the others can just
use it and should not obtain a new one */
if(!isObjectStillValid()) {
sharedObject = new SharedObject(/*some parameters from somewhere*/)
}
}
}
From what I have read from documentation and on stackoverflow, the synchronized keyword will assure only one thread can access the synchronised block on the same object instance(therefore write race/multiple unnecessary writes is a non-issue) while volatile keyword on the field reference will assure the reference value is written directly to the main program memory (not cached locally).
Are there any other pitfalls I am missing?
I want to be sure that within synchronized block when sharedObject is written to, the new value of sharedObject is present for any other thread at latest when lock for obtainNewSharedObject() is released. Should this not be guaranteed, I could encounter scenarios of unnecessary writes and replacing correct values which are a big problem for this case.
I know to be absolutely safe I could just make getSharedObjectString() synchronized by itself however as stated previously I do not want to block reading if not needed.
This way reading is non-blocking, when a write scenario occurs it is blocking.
I should probably mention method isObjectStillValid() is thread independant (entirely SharedObject and System clock based) therefore a valid Thread-free check to be used for write scenarios.
Edit: Please note I could not find a similar topic on stackoverflow, but it may exist. Sorry if that is the case.
Edit2: Thank you for all the comments. Edit because apparently I cannot upvote yet (I can, but it does not show). While my solution is functional as long as isObjectStillValid is thread-safe, it can suffer from decreased performance due to multiple accesses to volatile field. I will improve it most likely using the upgraded double-checked locking solution. I will also in-depth analyse all the other possibilities mentioned here.
Why don't you use AtomicReference. It uses optimistic locking, meaning that no actual thread locking is involved. Internally it uses Compare and Swap. If you look at the implementation it uses volatile in its implementation and I would trust Doug Lea to implement it correctly :)
Apart from this, there many more ways for synchronization between lot of readers and some writers - ReadWriteLock
This looks like a classic double-checked locking pattern. While your implementation is logically correct - thanks to the use of volatile on sharedObject - it might not be the most performant.
The recommended pattern for Java 1.5 on is shown on the Wikipedia page linked.
// Works with acquire/release semantics for volatile in Java 1.5 and later
// Broken under Java 1.4 and earlier semantics for volatile
class Foo {
private volatile Helper helper;
public Helper getHelper() {
Helper localRef = helper;
if (localRef == null) {
synchronized(this) {
localRef = helper;
if (localRef == null) {
helper = localRef = new Helper();
}
}
}
return localRef;
}
// other functions and members...
}
Note the use of a localRef for accessing the helper field. This limits access to the volatile field in the simple case to a single read instead of potentially twice; once for the check and once for the return. See the Wikipedia page again, just after the recommended pattern sample.
Note the local variable "localRef", which seems unnecessary. The effect of this is that in cases where helper is already initialized (i.e., most of the time), the volatile field is only accessed once (due to "return localRef;" instead of "return helper;"), which can improve the method's overall performance by as much as 25 percent.[7]
Depending on how isObjectStillValid() accesses sharedObject, you might benefit from a similar pattern.
This sounds like the use of a ReadWriteLock would be appropiate.
The basic idea is that there can be multiple readers simultaniously or one writer exclusively. Here can you find an Example how to use it in a List implementation.
Copy paste in case the side goes down:
import java.util.*;
import java.util.concurrent.locks.*;
/**
* ReadWriteList.java
* This class demonstrates how to use ReadWriteLock to add concurrency
* features to a non-threadsafe collection
* #author www.codejava.net
*/
public class ReadWriteList<E> {
private List<E> list = new ArrayList<>();
private ReadWriteLock rwLock = new ReentrantReadWriteLock();
public ReadWriteList(E... initialElements) {
list.addAll(Arrays.asList(initialElements));
}
public void add(E element) {
Lock writeLock = rwLock.writeLock();
writeLock.lock();
try {
list.add(element);
} finally {
writeLock.unlock();
}
}
public E get(int index) {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return list.get(index);
} finally {
readLock.unlock();
}
}
public int size() {
Lock readLock = rwLock.readLock();
readLock.lock();
try {
return list.size();
} finally {
readLock.unlock();
}
}
}

Atomic copy-and-clear on Java collection

I know similar questions are often asked, but I could not find anything that would help me.
The situation is like this:
One worker is adding elements to collection
The second one is waiting for some time (maturity of elements) or for certain size of collection, and start it's job.
The thing is: how to copy (I think it's best to work on copy) the collection for second worker, and then clear original collection to ensure we won't lost anything (the first worker is writing all the time) but not to hold lock on original collection as short as possible?
thanks
This kind of thing will be far easier if you use the purpose-built concurrency tools like LinkedBlockingQueue rather than a plain HashSet. Have the producer add elements to the queue, and the consumer can use drainTo to extract elements from the queue in batches as it requires them. There's no need for any synchronization, as BlockingQueue implementations are designed to be threadsafe.
Ian's LinkedBlockingQueue solution is the simplest.
For higher throughput (potentially trade off with latency) in a single producer single consumer scenario, you may want to consider the example in java.util.concurrent.Exchanger
After swapping, you now have the whole collection yourself.
works for me
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MyClass {
private final Map<String, Integer> cachedData = new ConcurrentHashMap<>();
private final ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock sharedLock = lock.readLock();
private final Lock copyAndFlushLock = lock.writeLock();
public void putData(String key, Integer value) {
try {
sharedLock.lock();
cachedData.put(key, value);
} finally {
sharedLock.unlock();
}
}
public Collection<Integer> copyAndFlush() {
try {
copyAndFlushLock.lock();
Collection<Integer> values = cachedData.values();
cachedData.clear();
return values;
} finally {
copyAndFlushLock.unlock();
}
}
}

Java - using AtomicInteger vs Static int

While using multiple threads I have learnt to use Static variables whenever I want to use a counter that will be accessed by multiple threads.
Example:
static int count=0; Then later in the program I use it as count++;.
Today I came across something called AtomicInteger and I also learned that it is Thread safe and could use one of its methods called getAndInrement() to achieve the same effect.
Could anyone help me to understand about using static atomicInteger versus static int count?
- AtomicInteger is used to perform the atomic operation over an integer, its an alternative when you don't want to use synchronized keyword.
- Using a volatile on a Non-Atomic field will give inconsistent result.
int volatile count;
public void inc(){
count++
}
- static will make a variable shared by all the instances of that class, But still it will produce an inconsistent result in multi-threading environment.
So try these when you are in multithreading environment:
1. Its always better to follow the Brian's Rule:
When ever we write a variable which is next to be read by another
thread, or when we are reading a variable which is written just by
another thread, it needs to be synchronized. The shared fields must be
made private, making the read and write methods/atomic statements
synchronized.
2. Second option is using the Atomic Classes, like AtomicInteger, AtomicLong, AtomicReference, etc.
I agree with #Kumar's answer.
Volatile is not sufficient - it has some implications for the memory order, but does not ensure atomicity of ++.
The really difficult thing about multi-threaded programming is that problems may not show up in any reasonable amount of testing. I wrote a program to demonstrate the issue, but it has threads that do nothing but increment counters. Even so, the counts are within about 1% of the right answer. In a real program, in which the threads have other work to do, there may be a very low probability of two threads doing the ++ close enough to simultaneously to show the problem. Multi-thread correctness cannot be tested in, it has to be designed in.
This program does the same counting task using a simple static int, a volatile int, and an AtomicInteger. Only the AtomicInteger consistently gets the right answer. A typical output on a multiprocessor with 4 dual-threaded cores is:
count: 1981788 volatileCount: 1982139 atomicCount: 2000000 Expected count: 2000000
Here's the source code:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class Test {
private static int COUNTS_PER_THREAD = 1000000;
private static int THREADS = 2;
private static int count = 0;
private static volatile int volatileCount = 0;
private static AtomicInteger atomicCount = new AtomicInteger();
public static void main(String[] args) throws InterruptedException {
List<Thread> threads = new ArrayList<Thread>(THREADS);
for (int i = 0; i < THREADS; i++) {
threads.add(new Thread(new Counter()));
}
for (Thread t : threads) {
t.start();
}
for (Thread t : threads) {
t.join();
}
System.out.println("count: " + count + " volatileCount: " + volatileCount + " atomicCount: "
+ atomicCount + " Expected count: "
+ (THREADS * COUNTS_PER_THREAD));
}
private static class Counter implements Runnable {
#Override
public void run() {
for (int i = 0; i < COUNTS_PER_THREAD; i++) {
count++;
volatileCount++;
atomicCount.incrementAndGet();
}
}
}
}
"static" make the var to be class level. That means, if you define "static int count" in a class, no matter how many instances you created of the class, all instances use same "count". While AtomicInteger is a normal class, it just add synchronization protection.
With AtomicInteger the incrementAndGet() guaranteed to be atomic.
If you use count++ to get the previous value it is not guaranteed to be atomic.
Something the I missed from your question - and was stated by other answer - static has nothing to do with threading.
static int counter would give you inconsistent result in multithreaded environment unless you make the counter volatile or make the increment block synchronized.
In case of automic it gives lock-free thread-safe programming on single variables.
More detail in automic's and link
I think there is no gurantee to see on count++ the newest value. count++ must read the value of count. Another Thread can have written a new value to count but stored it's value on the Thread local cache, i. e. does not flush to main memory. Also your Thread, that reads count, has no gurantee to read from the main memory, i. e. refresh from main memory. synchronize gurantees that.
AtomicInteger is to make the get and increment as an atomic process. It can be thought as a Sequencer in Database. It provides utility methods to increment, decrement delta int values.
static int can cause issue if you are getting counter and then processing and then updating it. AtomicInteger does it easily but you can't use it if you have to update the counter based on processing results.

Multithread communication: how good is the use of Atomic Variables like AtomicInteger? why is there no AtomicFloat?

Intro:
I want to create a multithreaded android app. My problem is the communication between the threads. I read about communication between threads and I came across stuff like Looper/Handler design, which seemed quite involved and Atomic Variables like AtomicInteger. For now, I used AtomicInteger as a communication but since I am not very experienced in Java, I am not sure if that is bad in my case/ if there is a better solution for my particular purpose. Also I got a little suspicious of my method, when I noticed I need actually something like AtomicFloat, but it's not existing. I felt like I am missusing the concept. I also found that you can make yourself an AtomicFloat, but I am just not sure if I am on the right way or if there is a better technique.
Question:
Is it ok/good to use Atomic Variables and implement also AtomicFloat for my particular purpose (described below) or is there a better way of handling the communication?
Purpose/Architecture of the App using AtomicVariables so far:
I have 4 Threads with the following purpose:
1.SensorThread: Reads sensor data and saves the most recent values in AtomicVariables like
AtomicFloat gyro_z,AtomicFloat gyro_y, ...
2.CommunicationThread: Communication with the PC, interprets commands which come form the socket and set the state of the app in terms of a AtomicInteger:
AtomicInteger state;
3.UIThread: Displays current sensor values from
AtomicFloat gyro_z,AtomicFloat gyro_y,
4.ComputationThread: uses sensor values AtomicFloat gyro_z,AtomicFloat gyro_y, ... and state AtomicInteger state to perform calculation and send commands over USB.
You basically have a readers writers problem, with two readers and (for the moment) only one writer. If you just want to pass simple types between threads, an AtomicInteger or a similarly implemented AtomicFloat will be just fine.
However, a more accommodating solution, which would enable you to work with more complex data types would be a ReadWriteLock protecting the code where you read or write your object data:
e.g.:
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); //the reentrant impl
....
public void readMethod() {
readWriteLock.readLock().lock();
try {
//code that simply _reads_ your object
} finally {
readWriteLock.readLock().unlock();
}
}
public void writeMethod() {
readWriteLock.writeLock().lock();
try {
//... code that modifies your shared object / objects
} finally {
readWriteLock.writeLock().unlock();
}
}
This will only enable "one writer-only" or "multiple reader" scenarios for access to your shared objects.
This would enable you for example to work with a complex type that looks like this:
public class SensorRead {
public java.util.Date dateTimeForSample;
public float value;
}
While using this data type you should care if the two fields are set and modified safely and atomically. The AtomicXXX type objects are not useful anymore.
You have to first ask yourself if you truly need the functionality of a theoretical AtomicFloat. The only benefit you could have over a simple volatile float is the compareAndSet and the addAndGet operations (since I guess increment and decrement don't really make sense in the case of floats).
If you really need those, you could probably implement them by studying the code of AtomicInteger e.g.:
public final int addAndGet(int delta) {
for (;;) {
int current = get();
int next = current + delta;
if (compareAndSet(current, next))
return next;
}
}
Now the only problem here is that compareAndSet uses platform-specific calls that don't exist for floats, so you'll probably need to emulate it by using the Float.floatToIntBits method to obtain an int, then use the CAS of AtomicInteger, something like:
private volatile float value;
public final boolean compareAndSet(float expect, float next) {
AtomicInteger local = new AtomicInteger();
for(;;) {
local.set(Float.floatToIntBits(value));
if(local.compareAndSet(Float.floatToIntBits(expect),
Float.floatToIntBits(next)) {
set(Float.intBitsToFloat(local.get()));
return true;
}
}
}
public final float addAndGet(float delta) {
for (;;) {
float current = get();
float next = current + delta;
if (compareAndSet(current, next))
return next;
}
}

Java Threading Tutorial Type Question

I am fairly naive when it comes to the world of Java Threading and Concurrency. I am currently trying to learn. I made a simple example to try to figure out how concurrency works.
Here is my code:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadedService {
private ExecutorService exec;
/**
* #param delegate
* #param poolSize
*/
public ThreadedService(int poolSize) {
if (poolSize < 1) {
this.exec = Executors.newCachedThreadPool();
} else {
this.exec = Executors.newFixedThreadPool(poolSize);
}
}
public void add(final String str) {
exec.execute(new Runnable() {
public void run() {
System.out.println(str);
}
});
}
public static void main(String args[]) {
ThreadedService t = new ThreadedService(25);
for (int i = 0; i < 100; i++) {
t.add("ADD: " + i);
}
}
}
What do I need to do to make the code print out the numbers 0-99 in sequential order?
Thread pools are usually used for operations which do not need synchronization or are highly parallel.
Printing the numbers 0-99 sequentially is not a concurrent problem and requires threads to be synchronized to avoid printing out of order.
I recommend taking a look at the Java concurrency lesson to get an idea of concurrency in Java.
The idea of threads is not to do things sequentially.
You will need some shared state to coordinate. In the example, adding instance fields to your outer class will work in this example. Remove the parameter from add. Add a lock object and a counter. Grab the lock, increment print the number, increment the number, release the number.
The simplest solution to your problem is to use a ThreadPool size of 1. However, this isn't really the kind of problem one would use threads to solve.
To expand, if you create your executor with:
this.exec = Executors.newSingleThreadExecutor();
then your threads will all be scheduled and executed in the order they were submitted for execution. There are a few scenarios where this is a logical thing to do, but in most cases Threads are the wrong tool to use to solve this problem.
This kind of thing makes sense to do when you need to execute the task in a different thread -- perhaps it takes a long time to execute and you don't want to block a GUI thread -- but you don't need or don't want the submitted tasks to run at the same time.
The problem is by definition not suited to threads. Threads are run independently and there isn't really a way to predict which thread is run first.
If you want to change your code to run sequentially, change add to:
public void add(final String str) {
System.out.println(str);
}
You are not using threads (not your own at least) and everything happens sequentially.

Categories

Resources