I am counting votes for electronic election and I have only one party in my initial version. There will be different threads per voter and the threads will update the votes count of a given party.
I decided to use ConcurrentHashMap, but the results are not what I expected...
Map<String, Integer> voting = new ConcurrentHashMap<>();
for (int i = 0; i < 16; i++) {
new Thread(() -> {
voting.put("GERB", voting.getOrDefault("GERB", 0) + 1);
}).start();
}
for (int i = 0; i < 100; i++) {
voting.put("GERB", voting.getOrDefault("GERB", 0) + 1);
}
Thread.sleep(5000); // Waits for the threads to finish
for (String s : voting.keySet()) {
System.out.println(s + ": " + voting.get(s));
}
The result is different every time - it ranges from 114 to 116.
Isn't ConcurrentHashMap supposed to be synchronised?
Well, there's a compound action here. You get the map value given a key, increment it by one, and place it back in the map against the same key. You have to guarantee that all these statements execute atomically. But the given implementation does not impose that prerequisite. Hence you end up with a safety failure.
To fix this, you can use the atomic merge operation defined in ConcurrentHashMap. The entire method invocation is performed atomically. Here's how it looks.
Map<String, Integer> voting = new ConcurrentHashMap<>();
for (int i = 0; i < 16; i++)
new Thread(() -> {
voting.merge("GERB", 1, Integer::sum);
}).start();
for (int i = 0; i < 100; i++)
voting.merge("GERB", 1, Integer::sum);
Thread.sleep(5000); // Waits for the threads to finish
for (String s : voting.keySet())
System.out.println(s + ": " + voting.get(s));
Running this program produces the following output:
GERB: 116
Assume there are two or more threads performs
voting.put("GERB", voting.getOrDefault("GERB", 0) + 1);
what happens?
Lets say value on key "GERB" now equals 10
Thread #1 gets value voting.getOrDefault("GERB", 0). It is 10
Thread #2 gets value voting.getOrDefault("GERB", 0). It is 10
Thread #1 adds 1, now it is 11
Thread #2 adds 1, now it is 11
Thread #1 writes values 11 back to voting
Thread #2 writes values 11 back to voting
Now, although 2 threads completes, the value increased only by 1 because of concurency.
So, yes, methods of ConcurrentHashMap are synchronized. That means, when one thread executes e.g. put, another thread waits. But they do not synchronize threads outside anyhow.
If you perform several calls you have to synchronize them on your own. E.g.:
final Map<String, Integer> voting = new ConcurrentHashMap<>();
for (int i = 0; i < 16; i++) {
new Thread(() -> {
synchronized (voting) { // synchronize the whole operation over the same object
voting.put("GERB", voting.getOrDefault("GERB", 0) + 1);
}
}).start();
}
UPD
As it noted in the comments, keep in mind that synchronization over voting object does not guarantee synchronization with ConcurentHahMap's methods itself. You have to perform that synchronization for every call to voting methods if those calls can be performed concurrently. In fact, you can use any other object to synchronize (it's not required to be voting): it only needs to be the same for all the threads.
But, as it noted by #Holger, this defeats the very purpose of the ConcurentHashMap.
To utilize the atomic mechanics of ConcurentHashMap without locking the threads you can use method replace to retry the operation if the value was altered by another thread:
for (int i = 0; i < 16; i++) {
new Thread(() -> {
Integer oldValue, newValue;
do {
oldValue = voting.getOrDefault("GERB", 0);
newValue = oldValue + 1; // do some actions over the value
} while (!voting.replace("GERB", oldValue, newValue)); // repeat if the value was changed
}).start();
}
You can divide this line voting.put("GERB", voting.getOrDefault("GERB", 0) + 1); into three steps:
int temp=voting.getOrDefault("GERB",0); //1
temp++; //2
voting.put("GERB",temp); //3
Now between line1 and line3, Other thread can change the value associated with "GERB" because the method has return, there is nothing can stop other thread from changing it. So when you call voting.put("GERB",temp),you override their value which makes their update lost.
Related
My question is extremely basic: once I have written some array values by one or more threads (phase 1), how can I 'publish' my array to make all the changes visible to other threads (phase 2)?
I have code that does all the array writing, then all the array reading, then again all the writing, then again all the reading etc. I'd like to do it in multiple threads, so multiple threads first would do the array writing phase, then multiple threads would do the array reading phase etc.
My concern is how to safely publish the array writes after each writing phase.
Consider the following simplified thread-unsafe code, that does just one writing phase with just one thread and then just one reading phase with multiple threads:
ExecutorService executor = Executors.newFixedThreadPool(5);
double[] arr = new double[5];
for (int i=0; i<5; ++i) {
arr[i] = 1 + Math.random();
}
for (int i=0; i<5; ++i) {
final int j=i;
executor.submit(() -> System.out.println(String.format("arr[%s]=%s", j, arr[j])));
}
The code normally prints non-zero values, but I understand that it might occasionally print zeros as well, as the array is not properly published by the writing thread, so some writes might not be visible to other threads.
I'd like to fix this problem and write the above code properly, in a thread-safe manner, i.e. to make sure that all my writes will be visible to the reading threads.
1. Could you advise on the best way to do so?
The concurrent collections and AtomicXxxArray are not an option for me because of performance (and also code clarity), as I have 2D arrays etc.
2. I can think of the following possible solutions, but I am not 100% sure they would work. Could you also advise on the solutions below?
Solution 1: assignment to a final array
Justification: I expect a final field to be always properly initialized with the latest writes, including all its recursive dependencies.
for (int i=0; i<5; ++i) {
arr[i] = 1 + Math.random();
}
final double[] arr2 = arr; //<---- safe publication?
for (int i=0; i<5; ++i) {
final int j=i;
executor.submit(() -> System.out.println(String.format("arr[%s]=%s", j, arr2[j])));
}
Solution 2: a latch
Justification: I expect the latch to establish a perfect happens-before relationship between the writing thread(s) and the reading threads.
CountDownLatch latch = new CountDownLatch(1); //1 = the number of writing threads
for (int i=0; i<5; ++i) {
arr[i] = Math.random();
}
latch.countDown(); //<- writing is done
for (int i=0; i<5; ++i) {
final int j=i;
executor.submit(() -> {
try {latch.await();} catch (InterruptedException e) {...} //happens-before(writings, reading) guarantee?
System.out.println(String.format("arr[%s]=%s", j, arr[j]));
});
}
Update: this answer https://stackoverflow.com/a/5173805/1847482 suggests the following solution:
volatile int guard = 0;
...
//after the writing is done:
guard = guard + 1; //write some new value
//just before the reading: read the volatile variable, e.g.
guard = guard + 1; //includes reading
... //do the reading
This solution uses the following rule: "if thread A writes some non-volatile stuff and a volatile variable after that, thread B is guaranteed to see the changes of the volatile stuff as well if it reads the volatile variable first".
Your first example is perfectly safe, because the tasks originate from the writer thread. As the docs say:
Actions in a thread prior to the submission of a Runnable to an Executor happen-before its execution begins.
I have created some callable threads in a for loop, in my main method and started all of them.
After starting all threads I have Thread.sleep(10000). In this case what happens to my child callable threads.
psudocode:
public static void main(String[] args){
Map<String, String> columnNames_TypesMap = tableUtil.getColumnNamesAndTypesFromOracleDB(toTable);
ExecutorService executor = Executors.newFixedThreadPool(50);
Set<Future<String>> values = Collections.newSetFromMap(new ConcurrentHashMap<Future<String>, Boolean>());
Future<String> value = null;
boolean valueSizeLogged = false;
long preValuesSize = values.size();
outer: while (true) {
//In the below method I am reducing values size.
count = tableUtil.checkIfAllRowsCopied(values, count, totalNoOfRecordsInFromTable);
if (values.size() > 5) {
logger.info("****** Hence we do not create new threads. We do wait for the created threads to compelte");
Thread.sleep(sleepTime);//Here I am putting my main thread to sleep
continue outer;
}
for (int indexForThread = 1; indexForThread <= 15; indexForThread++) {
startingRange = endingRanges + 1;
endingRanges = endingRanges + maxNoOfRecordsPerThread;
Callable<String> callable2 = new InsertionCallable(as400SchemaName + "." + fromTable, startingRange, endingRanges, columnNames_TypesMap, toTable);
value = executor.submit(callable2);//Child Thread
values.add(value);
}
}
}
In the above code first i have created 15 Threads. in the second loop(outer while), I am doing Thread.sleep() if values size is greater than 5, at this point of time what will happen to the created child threads? Will Child threads also goes to Sleep mode or what happens to Child Threads.
Kindly help. Your help will be highly appreciable.
Thanks.
The child threads are not affected by the parent thread sleeping (or terminating, or pretty much anything else). They will happily chug along.
Whenever I run this program it gives me different result. Can someone explain to me, or give me some topics where I could find answer in order to understand what happens in the code?
class IntCell {
private int n = 0;
public int getN() {return n;}
public void setN(int n) {this.n = n;}
}
public class Count extends Thread {
static IntCell n = new IntCell();
public void run() {
int temp;
for (int i = 0; i < 200000; i++) {
temp = n.getN();
n.setN(temp + 1);
}
}
public static void main(String[] args) {
Count p = new Count();
Count q = new Count();
p.start();
q.start();
try { p.join(); q.join(); }
catch (InterruptedException e) { }
System.out.println("The value of n is " + n.getN());
}
}
The reason is simple: you don't get and modify your counter atomically such that your code is prone to race condition issues.
Here is an example that illustrates the problem:
Thread #1 calls n.getN() gets 0
Thread #2 calls n.getN() gets 0
Thread #1 calls n.setN(1) to set n to 1
Thread #2 is not aware that thread #1 has already set n to 1 so still calls n.setN(1) to set n to 1 instead of 2 as you would expect, this is called a race condition issue.
Your final result would then depend on the total amount of race condition issues met while executing your code which is unpredictable so it changes from one test to another.
One way to fix it, is to get and set your counter in a synchronized block in order to do it atomically as next, indeed it will enforce the threads to acquire an exclusive lock on the instance of IntCell assigned to n before being able to execute this section of code.
synchronized (n) {
temp = n.getN();
n.setN(temp + 1);
}
Output:
The value of n is 400000
You could also consider using AtomicInteger instead of int for your counter in order to rely on methods of type addAndGet(int delta) or incrementAndGet() to increment your counter atomically.
The access to the IntCell n static variable is concurrent between your two threads :
static IntCell n = new IntCell();
public void run() {
int temp;
for (int i = 0; i < 200000; i++) {
temp = n.getN();
n.setN(temp + 1);
}
}
Race conditions make that you cannot have a predictable behavior when n.setN(temp + 1); is performed as it depends on which thread has previously called :temp = n.getN();.
If it the current thread, you have the value put by the thread otherwise you have the last value put by the other thread.
You could add synchronization mechanism to avoid the problem of unexpected behavior.
You are running 2 threads in parallel and updating a shared variable by these 2 threads, that is why your answer is always different. It is not a good practice to update shared variable like this.
To understand, you should first understand Multithreading and then notify and wait, simple cases
You modify the same number n with two concurrent Threads. If Thread1 reads n = 2, then Thread2 reads n = 2 before Thread2 has written the increment, Thread1 will increment n to 3, but Thread2 will no more increment, but write another "3" to n. If Thread1 finishes its incrementation before Thread2 reads, both will increment.
Now both Threads are concurrent and you can never tell which one will get what CPU cycle. This depends on what else runs on your machine. So You will always lose a different number of incrementations by the above mentioned overwriting situation.
To solve it, run real incrementations on n via n++. They go in a single CPU cycle.
I just want to see the difference between them visually, so below is the code. But it always fails. Can someone please help me on this? I have seen questions on SO too, but none of them have shown the difference programatically.
public class BBDifferencetest {
protected static int testnum = 0;
public static void testStringBuilder() {
final StringBuilder sb = new StringBuilder();
Thread t1 = new Thread() {
#Override
public void run() {
for (int x = 0; x < 100; x++) {
testnum++;
sb.append(testnum);
sb.append(" ");
}
}
};
Thread t2 = new Thread() {
public void run() {
for (int x = 0; x < 100; x++) {
testnum++;
sb.append(testnum);
sb.append(" ");
}
}
};
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Result is: " + sb.toString());
}
public static void main(String args[]) {
testStringBuilder();
}
}
When I execute this, I get the output sometimes in a random manner, so this proves my test. But when I even replace StringBuilder with StringBuffer and test, even it gives me unexpected output(rather than sequential which from 1 to 200). So can someone help me getting to know the difference visually?
P.S : If anyone has your code which shows the difference, I would be very glad to accept it as an answer. Because I am not sure whether I can achieve the difference with my code even though it is modified.
(rather than sequential which from 1 to 200)
Each thread is performing a read, modify, write operation on testnum. That in itself is not thread-safe.
Then each thread is fetching the value of testnum again in order to append it. The other thread may well have interrupted by then and incremented the value again.
If you change your code to:
AtomicInteger counter = new AtomicInteger();
...
sb.append(counter.getAndIncrement());
then you're more likely to see what you expect.
To make it clearer, change your loops to only call append once, like this:
for (int x = 0; x < 100; x++) {
sb.append(counter.incrementAndGet() + " ");
}
When I do that, for StringBuffer I always get "perfect" output. For StringBuilder I sometimes get output like this:
97 98 100 102 104
Here the two threads have both been appending at the same time, and the contents have been screwed up.
EDIT: Here's a somewhat shorter complete example:
import java.util.concurrent.atomic.AtomicInteger;
public class Test {
public static void main(String[] args) throws InterruptedException {
final AtomicInteger counter = new AtomicInteger();
// Change to StringBuffer to see "working" output
final StringBuilder sb = new StringBuilder();
Runnable runnable = new Runnable() {
#Override
public void run() {
for (int x = 0; x < 100; x++) {
sb.append(counter.incrementAndGet() + " ");
}
}
};
Thread t1 = new Thread(runnable);
Thread t2 = new Thread(runnable);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(sb);
}
}
StringBuffer is synchronized at the method level. It means that noone can enter one of his methods if a thread is already in one of his method. But it does not guarantee that one thread will be blocked to use StringBuilder at all as long as the other thread uses it, and so the two threads will still compete for access to methods, and you may have randomly a non-ordered result.
The only way to really lock an access to the StringBuffer is to put the code that access it in a synchronized block:
public void run() {
synchronized(sb) {
for (int x = 0; x < 100; x++) {
testnum++;
sb.append(testnum);
sb.append(" ");
}
}
}
If you don't do that, then Thread 1 can go into sb.append(testnum) and Thread 2 will wait at the entry of it, and when Thread 1 goes out, Thread 2 can potentially go inside and starts to write before Thread 1 enters sb.append(" "). So you would see:
12 13 1415 16 ....
The thing is, locking like this will make things work for StringBuilder also. That's why one could say that the synchronization mechanism on StringBuffer is quite useless, and therefore why it's not used anymore (the same thing for Vector).
So, doing this way can not show you the difference between StringBuilder and StringBuffer. The suggestion in Jon Skeet answer is better.
+1 for what Cyrille said. I imagine that it is only the nature of arrays of inherently atomic types (primitives <= 32 bit) that saves you from get a ConcurrentModificationException with the StringBuilder as you would with, say, appending to a List<Integer>
Basically, you have two threads, each 100 individual operations. The two compete for lock of the object before each append, and release it afterwards, 100 times each. The thread that wins on each iteration will be randomized by the (extremely) small amount of time taken to increment the loop counter and testnum.
More exemplary of the difference from your example is not necessarily the ordering, but ensuring that all insertions are actually accounted for when using a StringBuilder. It has no internal synchronization, so it's entirely possible that some will get munged or overwritten in the process. The StringBuffer will handle this with internal synchronization guaranteeing that all inserts make it in properly, but you'll need external synchronization such as Cyrille's example above to hold a lock for the entire iteration sequence of each thread to safely use a StringBuilder.
I'm working on a multithreaded program where each thread calculates the GCD for two numbers, stores the numbers and GCD into a TreeMap, and prints out the TreeMap after all the threads finish. What kind of method should I use to make sure that only one thread is storing the data at the same time, and how do I use the last thread to print the TreeMap when it is ready to print?
for (int i = 0; i < myList.size(); ++i) {
for (int j = i + 1; j < myList.size(); ++j) {
modulus1 = myList.get(i);
modulus2 = myList.get(j);
pool.execute(new ThreadProcessRunnable(modulus1, modulus2, myMap));
}
}
public void run() {
ThreadProcess process = null;
try {
// Only one thread should execute the following code
for (Map.Entry<BigInteger, ArrayList<BigInteger>> entry : myMap.entrySet()) {
System.out.println("key ->" + entry.getKey() + ", value->" + entry.getValue());
}
} catch (Exception e) {
System.err.println("Exception ERROR");
}
You must use syncronize(myMap) {...} block in places where you need to guarantee single thread access to the map.
As for printing the result by the last thread, you can use a boolean flag as a signal of completeness and check it every time. Don't forget to make it volatile to let each thread see its value changes.
UPD: Brian Goetz "Java Concurrency In Practice" is a strongly recommended reading.
//Only one thread should executes the following code
synchronize{
for (Map.Entry<BigInteger, ArrayList<BigInteger>> entry : myMap.entrySet()) {
System.out.println("key ->" + entry.getKey() + ", value->" + entry.getValue());
}
}
You can use Collections.synchronizedMap to make it thread safe. And use thread.join to make sure printing is done only when all threads are dead.
Edit: Do the printing in Main thread. Just before printing, call join on all threads.