I have a class
#Component
public class JmxConf implements Serializable {
private static final long serialVersionUID = 5586922486161726170L;
private AtomicInteger count = new AtomicInteger(0);
public AtomicInteger getCount() {
return count;
}
}
And I autowired this class to another
#Component
public class QueueListener {
private ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
#Autowired
private JmxConf jmxConf;
public doIt(){
if(jmxConf.getCount().get()>.....) {
jmxConf.getCount().incrementAndget();
......
executor.submit(new thread here);
jmxConf.getCount().decrementAndget();
}
}
}
We have one singleton bean which has a state but access to this state is controlled by an atomic variable. Will this class be thread-safe? And if not, why. Thanks
No it won't be atomic. You have a race here:
if(jmxConf.getCount().get()>.....) {
jmxConf.getCount().incrementAndget();
Imagine the scenario where the greater than is some number, just say 10.
if(jmxConf.getCount().get() > 10) {
jmxConf.getCount().incrementAndget();
What if, when the thread hits the if the value is 9. When it gets to the increment it was already incremented by another thread to 10 and now you increment it to a value of 11.
You should use compareAndSet.
while(true){
int value = jmxConf.getCount().get() + 1;
if(value > 10){
break;
}
if(mxConfg.getCount().compareAndSet(value-1, value){
executor.submit(new thread here);
jmxConf.getCount().decrementAndGet();
break;
}
}
You can read more on atomic references and compareAndSet offered by Java.
So why do we need the while(true)? The compareAndSet function takes two parameters
public final boolean compareAndSet(int expect, int update)
The method says "Try to update the AtomicInteger in a thread safe matter, here is the value I expect it to be currently and here is the value I want to update it with. If, when trying to do the update, the value of the AtomicInteger is what I expect than you can safely do the update. If it's not what I expect it to be then don't update it and notify me that you didn't update it."
Let's say we enter the if and the value is 5 if another thread is also trying to update the AtomicInteger with a value of 5 both threads will have an expectation of 5 as the parameter. Because it is thread-safe only one thread can win which means one will fail (the compareAndSet will return false on failure). In that case we should re-try the compareAndSet until we succeed or exceed the threshold in which we break.
AtomicInteger is thread-safe so this will be thread-safe.
Related
This question already has answers here:
Java MultiThreading skips loop and gives wrong result [duplicate]
(3 answers)
Closed 1 year ago.
I'm java beginner and it's first time to use thread.
class Counter2 {
private int value = 0;
public void increment() {
value++;
printCounter();
}
public void decrement() {
value--;
printCounter();
}
public void printCounter() {
System.out.println(value);
}
}
class MyThread3 extends Thread {
Counter2 sharedCounter;
public MyThread3(Counter2 c) {
this.sharedCounter = c;
}
public void run() {
int i = 0;
while (i <= 100) {
sharedCounter.increment();
sharedCounter.decrement();
try {
sleep((int) (Math.random() * 2));
} catch (InterruptedException e) {
}
// System.out.println(i);
i++;
}
}
}
public class MyTest {
public static void main(String[] args) {
Thread t1, t2;
Counter2 c = new Counter2();
t1 = new MyThread3(c);
t1.start();
t2 = new MyThread3(c);
t2.start();
}
}
This code has 2 threads and 1 Counter, which is shared between the threads. The threads just repeat plus 1, minus 1 to the counter value. So, if I guess, the result should be 0. Because initial value was 0 and the number of incremented and decremented are the same. But some times the last printing number is not the 0, but -1 or -2 etc. please explain why this is this.
The Answer by Ranwala is correct.
AtomicInteger
An alternative solution I prefer is the use of the Atomic… classes. Specifically here, AtomicInteger. This class is a thread-safe wrapper around an integer.
Change your member field from Counter2 sharedCounter; to AtomicInteger sharedCounter;. Then use the various methods on that class to increment, to decrement, and to interrogate for current value.
You can then discard your Counter2 class entirely.
Executors
Also, you should know that in modern Java, we rarely need to address the Thread class directly. Instead we use the executors framework added to Java 5.
Define your tasks as either a Runnable or Callable. No need to extend from Thread.
See tutorial by Oracle, and search existing posts here on Stack Overflow.
There are two issues here. They are atomicity and visibility aspects of concurrency. Both increment and decrement are compound actions and need to be atomically performed in a multi-threaded environment. Apart from that you should not read a stale value whenever you read the counter. None of these are guaranteed by your current implementation.
Coming back to the solution, one naive way of achieving this is by using synchronized methods which uses a lock on the current instance to achieve the thread-safety. But that comes at a fairly high cost and incurs more lock overhead.
A much better approach would be to use CAS based non-blocking synchronization to achieve the task at hand. Here's how it looks in practice.
class Counter2 {
private LongAdder value = new LongAdder();
public void increment() {
value.increment();;
printCounter();
}
public void decrement() {
value.decrement();;
printCounter();
}
public void printCounter() {
System.out.println(value.intValue());
}
}
Since you are a beginner, I would recommend you to read the great book Java Concurrency in Practice 1st Edition which explains all these basics in a very nice, graspable manner by some of the great authors in our era ! If you have any questions about the contents of the book, you are welcome to post the questions here too. Read it from cover to cover at least twice !
Update
CAS is so called ComparaAndSwap is a lock free synchronization scheme achieved by using low level CPU instructions. Here it reads the value of the counter before the increment/decrement and then at the time it is updated, it checks whether the initial value is still there. If so, it updates the value successfully. Otherwise, chances are that another thread concurrently updating the value of the counter, hence the increment/decrement operation fails and it retries it again.
I am referencing from Baeldung.com. Unfortunately, the article does not explain why this is not a thread safe code. Article
My goal is to understand how to create a thread safe method with the synchronized keyword.
My actual result is: The count value is 1.
package NotSoThreadSafe;
public class CounterNotSoThreadSafe {
private int count = 0;
public int getCount() { return count; }
// synchronized specifies that the method can only be accessed by 1 thread at a time.
public synchronized void increment() throws InterruptedException { int temp = count; wait(100); count = temp + 1; }
}
My expected result is: The count value should be 10 because of:
I created 10 threads in a pool.
I executed Counter.increment() 10 times.
I make sure I only test after the CountDownLatch reached 0.
Therefore, it should be 10. However, if you release the lock of synchronized using Object.wait(100), the method become not thread safe.
package NotSoThreadSafe;
import org.junit.jupiter.api.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static org.junit.jupiter.api.Assertions.assertEquals;
class CounterNotSoThreadSafeTest {
#Test
void incrementConcurrency() throws InterruptedException {
int numberOfThreads = 10;
ExecutorService service = Executors.newFixedThreadPool(numberOfThreads);
CountDownLatch latch = new CountDownLatch(numberOfThreads);
CounterNotSoThreadSafe counter = new CounterNotSoThreadSafe();
for (int i = 0; i < numberOfThreads; i++) {
service.execute(() -> {
try { counter.increment(); } catch (InterruptedException e) { e.printStackTrace(); }
latch.countDown();
});
}
latch.await();
assertEquals(numberOfThreads, counter.getCount());
}
}
This code has both of the classical concurrency problems: a race condition (a semantic problem) and a data race (a memory model related problem).
Object.wait() releases the object's monitor and another thread can enter into the synchronized block/method while the current one is waiting. Obviously, author's intention was to make the method atomic, but Object.wait() breaks the atomicity. As result, if we call .increment() from, let's say, 10 threads simultaneously and each thread calls the method 100_000 times, we get count < 10 * 100_000 almost always, and this isn't what we'd like to. This is a race condition, a logical/semantic problem. We can rephrase the code... Since we release the monitor (this equals to the exit from the synchronized block), the code works as follows (like two separated synchronized parts):
public void increment() {
int temp = incrementPart1();
incrementPart2(temp);
}
private synchronized int incrementPart1() {
int temp = count;
return temp;
}
private synchronized void incrementPart2(int temp) {
count = temp + 1;
}
and, therefore, our increment increments the counter not atomically. Now, let's assume that 1st thread calls incrementPart1, then 2nd one calls incrementPart1, then 2nd one calls incrementPart2, and finally 1st one calls incrementPart2. We did 2 calls of the increment(), but the result is 1, not 2.
Another problem is a data race. There is the Java Memory Model (JMM) described in the Java Language Specification (JLS). JMM introduces a Happens-before (HB) order between actions like volatile memory write/read, Object monitor's operations etc. https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5 HB gives us guaranties that a value written by one thread will be visible by another one. Rules how to get these guaranties are also known as Safe Publication rules. The most common/useful ones are:
Publish the value/reference via a volatile field (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5), or as the consequence of this rule, via the AtomicX classes
Publish the value/reference through a properly locked field (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.4.5)
Use the static initializer to do the initializing stores
(http://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4)
Initialize the value/reference into a final field, which leads to the freeze action (https://docs.oracle.com/javase/specs/jls/se11/html/jls-17.html#jls-17.5).
So, to have the counter correctly (as JMM has defined) visible, we must make it volatile
private volatile int count = 0;
or do the read over the same object monitor's synchronization
public synchronized int getCount() { return count; }
I'd say that in practice, on Intel processors, you read the correct value without any of these additional efforts, with just simple plain read, because of TSO (Total Store Ordering) implemented. But on a more relaxed architecture, like ARM, you get the problem. Follow JMM formally to be sure your code is really thread-safe and doesn't contain any data races.
Why int temp = count; wait(100); count = temp + 1; is not thread-safe? One possible flow:
First thread reads count (0), save it in temp for later, and waits, allowing second thread to run (lock released);
second thread reads count (also 0), saved in temp, and waits, eventually allowing first thread to continue;
first thread increments value from temp and saves in count (1);
but second thread still holds the old value of count (0) in temp - eventually it will run and store temp+1 (1) into count, not incrementing its new value.
very simplified, just considering 2 threads
In short: wait() releases the lock allowing other (synchronized) method to run.
Let's take this simple class:
public class CounterService {
private volatile Counter counter;
public CounterService(Counter counter) {
this.counter = counter;
}
public long getCounterValue() {
System.out.println("GET: " + this.counter.counter + " in thread " +
Thread.currentThread().getName());
return this.counter.counter;
}
public long setCounterValue(long newValue) {
this.counter = this.counter.updateCounter(newValue);
System.out.println("--set: " + newValue + " in thread " +
Thread.currentThread().getName());
return this.counter.counter;
}
}
public class Counter {
public final long counter;
public Counter(long counter) {
this.counter = counter;
}
public Counter updateCounter(long i) {
return new Counter(i);
}
}
Now I want to write the unit test, that will always pass, if the CounterService is thread safe (eg. when I set get and set methods synchronized). I belive that writing a test, which will always fail if this class isn't thread safe, may be impossible.
I tried with something like this:
#Test
public void multipleThreadSetAndGetShouldCorrectValue() throws ExecutionException, InterruptedException {
int threads = 10;
final Counter counter = new Counter(0);
final CounterService counterService = new CounterService(counter);
CountDownLatch latch = new CountDownLatch(1);
ExecutorService executorService = Executors.newFixedThreadPool(threads);
Collection<Future<Long>> results = new ArrayList<>();
AtomicLong sequence = new AtomicLong(0);
for (int i = 0; i < threads; i++) {
results.add(executorService.submit(() -> {
latch.await(1, TimeUnit.SECONDS);
latch.countDown();
counterService.setCounterValue(sequence.getAndIncrement());
return counterService.getCounterValue();
}));
}
final Set<Long> uniqueResult = new HashSet<>();
for (Future<Long> result : results) {
uniqueResult.add(result.get());
}
assertEquals(threads, uniqueResult.size());
}
But this test will occasionally fail even if the CounterService is thread safe.
How to write unit test that will always pass when the class is thread safe? How to write test to check, that get method returns the last set value, even if it was modified by another thread?
First, your Counter class is pointless. The updateCounter method doesn't update, it returns a new object. So just delete the Counter class and use long in your CounterService.
There then remains the question as to what CounterService is for. It just wraps a long.
But disregarding that. No - you can't really write a test to prove that something is not thread-safe as multi-threading problems are not deterministic. You could insert delays into places where you know race conditions might occur, but that only works if you already know it isn't thread-safe in a particular place and you want to prove it. But if you don't know where the problem is you might not be able to insert the delays in the right place to prove the possible problem does exist.
By the same token, you can't really prove that it is correct either, although again you can increase your chances by inserting sleeps between operations to force problems. But it may not work and you are not testing the real-world scenario.
Your test is failing because you don't understand what synchronized does and what thread-safely implies.
In your test, you are setting a counter value and then getting it in the next line. If you synchronize the set and the get, all that means is that the individual get and set operations are thread-safe. It doesn't mean that you can call get and set separately and that get will return the same value that the previous set used.
If you want to set something and then get the same value back again safely you have to wrap the get and the set calls in a synchronized block.
synchonized(this) { // get must return same thing that was set
set
get
}
I strongly recommend that you focus on understanding what your program needs to achieve and what thread-safety and sychronization means in that context. Otherwise, you won't be able to develop a correct test anyway.
I am trying to practice synchronize keyword with methods.
I wrote the following code:
Adder class:
public class Adder implements Runnable{
Counter counter;
Adder(Counter counter){
this.counter = counter;
}
public void run() {
for (int i=0; i<100; i++)
counter.setCount(counter.getCount()+1);
}
}
Counter class:
public class Counter {
private int count = 0;
public synchronized void setCount(int val){
count = val;
}
public synchronized int getCount(){
return count;
}
}
main:
public class main {
public static void main(String[] args) {
Counter counter = new Counter();
Adder adder = new Adder(counter);
Thread t1 = new Thread(adder);
Thread t2 = new Thread(adder);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(counter.getCount());
}
}
I would expect the output of this to be 200, but it's not deterministic (theoretically, can have any value between 0-200). I suspect the problems is that I am using the getter and setter inline, i.e.
counter.setCount(counter.getCount()+1);
For some reason this "breaks" the mutual exclusion that I am trying to achieve with synchronization, but I can't see why.
I implemented the 1's addition with count++ like so:
public synchronized void add1(){
count++;
}
This worked, maybe because this way I use only one function instead of two inline. Could you explain why the first implementation doesn't work?
Calling the getter and subsequent calling of setter is two independent operations. "Set the result of getter plus one" is not atomic here. So you may perfectly have two gets returning the same value, and two sets of the same value increased by one.
Assume count is 100. You have two threads calls calling the getter, both getting 100. Then they both call the setter, setting 101. So the counter is now 101, not 102 - and both threads "were there" already.
So the result is non-deterministic and depends on the actual order of get/set operations from the two threads.
counter.setCount(counter.getCount()+1); is NOT atomic and it involves 3 steps:
(1) Read the value of count
(2) Add one to count
(3) Write the value of count
In the first approach, you are getting the locks independently i.e., in between the get and set calls of one thread there will be an interference of other threads. So you can't guarantee that the first thread read value is the same as when it comes for the writing.
In the second approach, you are holding the lock and performing all of the above 3 steps, so you will not find any problem.
Also, you can also solve your problem by using the threadsafe AtomicInteger class.
As part of our University coursework we have to make a multi threading download server in Java.
Everything is running smoothly apart from one bit : we have to have the server show the total number of downloads for each item each time it is downloaded. So far I have gotten it to work unless both clients request it at the same time. The code is below, If any one has any ides I would be very grateful. Also we must include thread.sleep part and must increment the counter in that convoluted way.
//Snipper from Protocol.java
if (theInput.equals("1")) {
theOutput = "The program displays a message... Another? Y or N";
DownloadCounter counter = new DownloadCounter();
count = DownloadCounter.getcount();//count is a var in Protocol.java it is static
int tmp = count;
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
System.out.println("sleep interrupted");
}
count = tmp + 1;
DownloadCounter.setcount(count);
System.out.println("Download Total " + count);
state = ANOTHER;
The DownloadCounter:
//DownloadCounter.java
public class DownloadCounter {
private static int count;
public static synchronized int getcount(){
return count;
}
public static synchronized void setcount(int num){
DownloadCounter.count = num;
}
}
The fundamental problem is that you have two threads doing a get, increment and set, so consider this situation:
Thread 1: set(5) // now count is 5
Thread 1: get() // Thread 1 gets 5
Thread 2: get() // Thread 2 gets 5
Thread 2: increments its local copy of count to 6
Thread 1: increments its local copy of count to 6
Thread 2: set(6) // now the count is 6
Thread 1: set(6) // the count is still 6, but it should be 7!!!
The solution is to implement an increment method which increments the count in a thread safe manner:
public synchronized void increment()
{
count++;
}
You can also use an AtomicInteger and avoid the locking:
AtomicInteger count = new AtomicInteger(0);
public int getCount()
{
return count.get();
}
public void increment()
{
count.incrementAndGet();
}
You also stated that the counter should count the number of downloads for each item, however, your current code will not do that. Your current counter will count ALL of the downloads for ALL of the items. Hint: you're making everything in DownloadCounter static and that's not going to work well if you want to have a separate counter for each item.
DownloadCounter needs a method for incrementing. There's no safe way to increment the counter with only a getCount and setCount method.
Java has a class AtomicInteger for handling just this type of thing.
Also you are only calling static methods on DownloadCounter, so there is no need to create a new instance.
The key to make it correct is precisely to make the get/increment/set an atomic operation. Instead of the setCount method, there should be a synchronized incrementCount() method.
You could also avoid the synchronization completely by using an AtomicInteger and use its incrementAndGet() method inside the incrementCount() method.
Note that the instruction DownloadCounter counter = new DownloadCounter(); is completely unnecessary. The class should have a private constructor to prevent such unnecessary instantiations.