Need to understand the problem in AtomicInteger code usage in multithreaded environment - java

In one of the interview, a coding question was asked to me and I had to find the problem in that code and suggest proper solution.
Please find below the entire code:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
public class Atomic {
static AtomicInteger count = new AtomicInteger(0);
static int counter = 0;
public static class Runnable extends Thread {
public void run() {
while (count.getAndSet(1) != 0) {
try {
Thread.sleep(3000);
} catch (Exception e) {
}
}
counter = counter + 1;
count.set(0);
}
}
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
Runnable runnable = new Runnable();
executor.execute(runnable);
}
executor.shutdown();
}
}
This code is running properly. But question is , there is some problem in this code if number of threads get increased or if I run For loop for almost 10000 times.
I tried to find the problem, but couldn't find one.

There are several things wrong with this code. You've not stated with "there is some problem" means, but here are the things that jump out.
Firstly, the counter variable is not updated safely. Multiple threads don't have guaranteed visibility of the last-written value; nor do you have the guarantee that no other thread has updated its value in between the read and the write.
The simple solution to this: change counter to an AtomicInteger, and use getAndIncrement or incrementAndGet to increment it.
Secondly, public static class Runnable extends Thread { is extremely dubious.
Don't hide the names of commonly-known Java classes (this is hiding java.lang.Runnable)
Don't extend Thread directly, especially when all you need is a java.lang.Runnable to add execute with an ExecutorService.
A more suitable class declaration would be:
public static class MyRunnable implements Runnable {
(or whatever you want to call it)
Or you can just declare an anonymous class:
executor.execute(new Runnable() { /* body */ });
Or you can just declare a lambda:
executor.execute(() -> { /* body */ });
Thirdly, count doesn't really seem to be serving an obvious purpose here. The logic of the runnable seems to be:
If "flag" is false:
Set "flag" to true
Increment a variable
Set "flag" to false
Otherwise:
Wait 3 seconds
Try again
count is playing the role of "flag" here. It's effectively just an AtomicBoolean.
But you don't need a separate count variable at all, if you make the counter an AtomicInteger:
while (true) {
int current = counter.get();
if (counter.compareAndSet(current, current + 1)) {
// Nothing else is trying to update "current" at the same time:
// we updated it. Stop.
break;
}
// Something else is trying to update at the same time.
// Sleep for 3 seconds.
Thread.sleep(3000);
}

Related

Is synchronization better option for multithreading shared resources?

public class MyResource {
private int count = 0;
void increment() {
count++;
}
void insert() { // incrementing shared resource count
for (int i = 0; i < 100000000; i++) {
increment();
}
}
void insert1() { //incrementing shared resource count
for (int i = 0; i < 100000000; i++) {
increment();
}
}
void startThread() {
Thread t1 = new Thread(new Runnable() { //thread incrementing count using insert()
#Override
public void run() {
insert();
}
});
Thread t2 = new Thread(new Runnable() { //thread incrementing count using insert1()
#Override
public void run() {
insert1();
}
});
t1.start();
t2.start();
try {
t1.join(); //t1 and t2 race to increment count by telling current thread to wait
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void entry() {
long start = System.currentTimeMillis();
startThread(); //commenting insert(); insert1() gives output as time taken = 452(approx) 110318544 (obvious)
// insert(); insert1(); //commenting startThread() gives output as time taken = 452(approx) 200000000
long end = System.currentTimeMillis();
long time = end - start;
System.out.println("time taken = " + time);
System.out.println(count);
}
}
Program entry point is from entry() method.
1.Only using insert(); insert1(); (Normal method calling ) and commenting startThread()(which executes thread) gives me result as shown in code.
2.Now commenting insert(); insert1(); and using startThread()(which executes thread) gives me result as shown in code.
3.Now I synchronize increment() gives me output as time taken = 35738 200000000
As Above synchronizing avoids access of shared resource but on other hand it takes lot of time to process.
So what's use of this synchronizing if it decrease the performance ?
Sometimes you just want two or more things to go on at the same time. Imagine the server of a chat application or a program that updates the GUI while a long task is running to let the user know that processing is going on
You are not suppose to use synchronization to increase performance, you are suppose to use it in order to protect shared resources.
Is this a real code example? Because if you want to use threads here in order to split the work synchronize
increment()
is not the best approach...
EDIT
as described here, you can change the design of this specific code to divide the work between the 2 threads more efficiently.
i altered their example to fit your needs, but all the methods described there are good.
import java.util.*;
import java.util.concurrent.*;
import static java.util.Arrays.asList;
public class Sums {
static class Counter implements Callable<Long> {
private final long _limit;
Counter(long limit) {
_limit = limit;
}
#Override
public Long call() {
long counter = 0;
for (long i = 0; i <= _limit; i++) {
counter++
}
return counter;
}
}
public static void main(String[] args) throws Exception {
int counter = 0;
ExecutorService executor = Executors.newFixedThreadPool(2);
List <Future<Long>> results = executor.invokeAll(asList(
new Counter(500000), new Counter(500000));
));
executor.shutdown();
for (Future<Long> result : results) {
counter += result.get();
}
}
}
and if you must use synchronisation, AtomicLong will do a better job.
Performance is not the only factor. Correctness can also be very important. Here is another question that has some low level details about the keyword synchronized.
If you are looking for performance, consider using the java.util.concurrent.atomic.AtomicLong class. It has been optimized for fast, atomic access.
EDIT:
Synchonized is overkill in this use case. Synchronized would be much more useful for FileIO or NetworkIO where the calls are much longer and correctness is much more important. Here is the source code for AtomicLong. Volatile was chosen because it is much more performant for short calls that change shared memory.
Adding a synchronized keyword adds in extra java bytecode that does a lot of checking for the right state to get the lock safely. Volatile will put the data in main memory, which takes longer to access, but the CPU enforces atomic access instead of the jvm generating extra code under the hood.

Synchronization with nested class but with a global variable? (JAVA)

I am trying to figure what would be the best way to fix this broken concurrency issue with this kind of code. I have tried adding a lock around "index++" but is there a better way of achieving concurrency?
public class MainClass {
public static short index = 0;
public static void main(String[] args) {
MainClass testConc = new MainClass();
Thread thr1 = new Thread(testConc.new MyRunnable());
thr1.start();
Thread thr2 = new Thread(testConc.new MyRunnable());
thr2.start();
}
class MyRunnable implements Runnable {
private static final Object lock = new Object();
public void run() {
while (index < 99) {
System.out.println(index);
synchronized(lock) {
index++;
}
}
}
}
}
You should have the lock at the same level (MainClass) as the data it is used for protecting. Class variable index should actually have private scope, because synchronization only happens in-class.
Also, as pointed out by Tomáš in the comment, the variable should be marked as volatile, which guarantees that any changes to the its value are visible to all threads (since Java 5). This removes the need to synchronize read access to index. So the corrected code looks something like:
public class MainClass {
private static volatile short index = 0;
private static final Object lock = new Object();
...
If you want the program to output the indices from 0 to 98 in order and only once per index value, you need to modify the run() method into this:
public void run() {
while (index < 99) {
synchronized (lock) {
// double-check for threads that made it here
// before #index got incremented to 99 by the thread that
// made the final increment
if (index < 99) {
System.out.println(index);
index++;
}
}
}
}
Notice that a double-check for index < 99 is required because index may have been changed by an another thread after the value was evaluated in the while condition. You'll see this if you increase the number of threads that are spawned by MainClass using the old version of run().
AtomicInteger would be better than locking around index++
It is designed especially for that use case.
Also by locking you are not achieving concurrency but thread safety/atomicity (if implemented properly).
By the way, I don't see the 'broken concurrency issue' in your code.

Java Thread Race Condition with BlockingQueue

I have a potential race condition in my Java code that uses a BlockingQueue, and I'd like to know how to modify the code to avoid it:
private static BlockingQueue<FileToFTP> ftpQueue = new LinkedBlockingQueue<FileToFTP>();
private static boolean shuttingDown = false;
private static FileToFTP pendingFile = null;
private static int uploadsPending = 0;
private static Thread ftpThread = new Thread(new Runnable() {
public void run() {
try {
for(;;) {
FileToFTP f2f = ftpQueue.take(); // this blocks until there is something to take
// FIXME: If the main thread takes over right
// at this instant, then uploadsRemaining()
// is not correct!!
uploadsPending = 1;
int qs = ftpQueue.size();
logIt(qs, f2f);
pendingFile = f2f;
if(!doUploadFile(f2f.getPath(), f2f.getFilename(), f2f.getRenameTo(), f2f.isBinary())) {
if(shuttingDown) {
log.info("Upload " + f2f + " failed!");
} else {
ftpQueue.offer(f2f); // put it back on to retry later
}
uploadsPending = 0;
} else {
pendingFile = null;
uploadsPending = 0;
}
if(qs == 0) logIt("");
}
} catch (InterruptedException consumed) {
// Allow thread to exit
}
}
});
public static int uploadsRemaining() {
return ftpQueue.size() + uploadsPending;
}
Please see the "FIXME" comment in the code. Thanks!!
Maybe I'm misinterpreting what you want, but it sounds like you may be better off using an ExecutorService to actually run things. You can create those using Exectors.newSingleThreadExecutor() or Executors.newFixedThreadPool(2) (2 being an example of the number of threads for it to use).
You can then either .execute or .submit Runnables on the ExecutorService. submit will return a Future<T> object that can be used to track the status of a particular job submitted to an ExecutorService.
Having said that, you may need to create a new class to do it as the Runnable / Callable class would need to have a FileToFTP variable in it. (Side note: I try to avoid inner classes, so if you're wondering why I didn't suggest doing it that way...)
The problem then becomes "how do I tell how many files are pending?" Unfortunately, the only easy way is to make it a static property of another class... with either static get/set methods or as a public/protected property. An AtomicInteger is ideal for this, so you may want to consider using one as a protected static one in your calling class. It has dedicated increment/decrement commands as well as ones that both adjust the value and return it.

Synchronized Block inside the run method

Does using a synchronized block inside the run method makes any sense? I thought it does, as long as I'm using a relevant lock, not the instance of Runnable containing this run method. Reading the answers to similar questions on stackoverflow seemed to confirm this. I tried to write some simple code to test it and the synchronized block inside the run method doesn't prevent from data corruption:
public class Test {
public Test() {
ExecutorService es = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
es.execute(new Runnable() {
#Override
public void run() {
synchronized (lock) {
sum += 1;
}
}
});
}
es.shutdown();
while(!es.isTerminated()) {
}
}
private int sum = 0;
private final Object lock = new Object();
public static void main(String[] args) {
Test t = new Test();
System.out.println(t.sum);
}
}
Why this code generates incorrect results? Is this because the synchronized block or some other mistake? I feel like I'm missing something basic here.
It's possible your executor encounters some sort of unexpected error. If that happens you won't know it because you are not getting any return value to check.
Try switching to submit() instead of execute() and store a list of Future instances the Executor gives you. If the final sum is less than 1000, iterate the futures and get() each one. If an exception is raised you'll see what happened with that particular runnable task.
Apart from your simple example, which looks OK, you should be careful with synchronization in Runnables to prevent them from blocking each other when one Runnable waits for some resource to be released only by another Runnable later in the queue that has not started yet and never will since the current waiting Runnable must finish first.
With enough worker Threads executing the jobs this is less likely to occur, though.

Query regarding output of a simple Thread example

I'm trying to get started with learning threading in Java and here's a simple example that I tried from here
Here's my code :
A simple main class:
package com.vogella.Thread;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
// We will store the threads so that we can check if they are done
List<Thread> threads = new ArrayList<Thread>();
// We will create 500 threads
for (int i = 0; i < 500; i++) {
Runnable task = new MyRunnable(10000000L + i);
Thread worker = new Thread(task);
// We can set the name of the thread
worker.setName(String.valueOf(i));
// Start the thread, never call method run() direct
worker.start();
// Remember the thread for later usage
threads.add(worker);
}
int running = 0;
do {
running = 0;
for (Thread thread : threads) {
if (thread.isAlive()) {
running++;
}
}
System.out.println("We have " + running + " running threads. ");//-A
} while (running > 0);
}
}
and the MyRunnable class is as follows :
package com.vogella.Thread;
public class MyRunnable implements Runnable {
private final long countUntil;
MyRunnable(long countUntil) {
this.countUntil = countUntil;
}
#Override
public void run() {
long sum = 0;
for (long i = 1; i < countUntil; i++) {
sum += i;
}
System.out.println(sum);
System.out.println("Test123");
}
}
And this is my output
49999995000000
Test123
50000005000000
Test123
50000015000001
Test123...
However I dont understand why the line marked with comment A in Main.java never prints. Any insight on this would be helpful.
Thanks!
It should print. Check you're not missing it in the program output.
Try commenting out the println()'s in your Runnable
There are a few things wrong with that code in terms of best practices. Unless that site mentions them (too lazy to look), I might consider finding a different tutorial. Also, have you checked the entire output? It's probably printing. It is not guaranteed to print as the last thing as I am going to guess you're assuming.
It should be able to print something. A few ideas for testing:
comment the println statements in your runnable - maybe it gets printed but you don't see it because there's too much output on the console
add a System.println(threads.size()) before the do statement to see how many threads have been added (should print 500).
add a Thread.sleep(100) before the do statement. Maybe the first thread gets alive after the do-while block has finished...

Categories