I am slightly surprised by what I get if I compile and run the following (horrible non-synchronized) Java SE program.
public class ThreadRace {
// this is the main class.
public static void main(String[] args) {
TestRunnable tr=new TestRunnable(); // tr is a Runnable.
Thread one=new Thread(tr,"thread_one");
Thread two=new Thread(tr,"thread_two");
one.start();
two.start(); // starting two threads both with associated object tr.
}
}
class TestRunnable implements Runnable {
int counter=0; // Both threads can see this counter.
public void run() {
for(int x=0;x<1000;x++) {
counter++;
}
// We can't get here until we've added one to counter 1000 times.
// Can we??
System.out.println("This is thread "+
Thread.currentThread().getName()+" and the counter is "+counter);
}
}
If I run "java ThreadRace" at the command line, then here is my interpretation
of what happens. Two new threads are created and started. The threads have
the same Runnable object instance tr, and so they see the same tr.counter .
Both new threads add one to this counter 1000 times, and then print the value
of the counter.
If I run this lots and lots of times, then usually I get output of the form
This is thread thread_one and the counter is 1000
This is thread thread_two and the counter is 2000
and occasionally I get output of the form
This is thread thread_one and the counter is 1204
This is thread thread_two and the counter is 2000
Note that what happened in this latter case was that thread_one finished
adding one to the counter 1000 times, but thread_two had started adding
one already, before thread_one printed out the value of the counter.
In particular, this output is still comprehensible to me.
However, very occasionally I get something like
This is thread thread_one and the counter is 1723
This is thread thread_two and the counter is 1723
As far as I can see, this "cannot happen". The only way the System.out.println() line
can be reached in either thread, is if the thread has finished counting to 1000.
So I am not bothered if one of the threads reports the counter as being some
random number between 1000 and 2000, but I cannot see how both threads can
get as far as their System.out.println() line (implying both for loops have finished,
surely?) and counter not be 2000 by the time the second statement is printed.
Is what is happening that both threads somehow attempt to do counter++ at exactly
the same time, and one overwrites the other? That is, a thread can even be
interrupted even in the middle of executing a single statement?
The "++" operator is not atomic -- it doesn't happen in one uninterruptible cycle. Think of it like this:
1. Fetch the old value
2. Add one to it
3. Store the new value back
So imagine that you get this sequence:
Thread A: Step 1
Thread B: Step 1
Thread A: Step 2
Thread B: Step 2
Thread A: Step 3
Thread B: Step 3
Both threads think they've incremented the variable, but its value has only increased by one! The second "store back" operation effectively cancels out the result of the first.
Now, truth is, when you add in multiple levels of cache, far weirder things can actually happen; but this is an easy explanation to understand. You can fix these kinds of issues by synchronizing access to the variable: either the whole run() method, or the inside of the loop using a synchronized block. As Jon suggests, you could also use some of the fancier tools in java.util.concurrent.atomic.
It absolutely can happen. counter++ isn't an atomic operation. Consider it as:
int tmp = counter;
tmp++;
counter = tmp;
Now imagine two threads executing that code at the same about time:
Both read the counter
Both increment their local copy (0 to 1)
Both write 1 into counter
This sort of thing is precisely why java.util.concurrent.atomic exists. Change your code to:
class TestRunnable implements Runnable {
private final AtomicInteger counter = new AtomicInteger();
public void run() {
for(int x=0;x<1000;x++) {
counter.incrementAndGet();
}
System.out.println("This is thread "+
Thread.currentThread().getName()+" and the counter is " + counter.get());
}
}
That code is safe.
Related
Here is my code,
class Shared {
private static int index = 0;
public synchronized void printThread() {
try {
while(true) {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + ": " + index++);
notifyAll();
// notify();
wait();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class Example13 implements Runnable {
private Shared shared = new Shared();
#Override
public void run() {
shared.printThread();
}
}
public class tetest {
public static void main(String[] args) {
Example13 r = new Example13();
Thread t1 = new Thread(r, "Thread 1");
Thread t2 = new Thread(r, "Thread 2");
Thread t3 = new Thread(r, "Thread 3");
Thread t4 = new Thread(r, "Thread 4");
Thread t5 = new Thread(r, "Thread 5");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
and the result is here
Thread 1: 0
Thread 5: 1
Thread 4: 2
Thread 3: 3
Thread 2: 4
Thread 3: 5
Thread 2: 6
Thread 3: 7
Thread 2: 8
Thread 3: 9
the question is, why only two of the threads are working? I'm so confused, I thought notify() is randomly wake up one of the waiting threads, but it's not.
is this starvation? then, why the starvation is caused? I tried notify() and notifyAll(), but got same results for both.
Can any one help my toasted brain?
This isn't 'starvation'. Your 5 threads are all doing nothing. They all want to 'wake up' - notify() will wake up an arbitrary one. It is neither unreliably random: The JMM does not ascribe an order to this, so one of them will wake up, you can't rely on it being random (do not use this to generate random numbers), nor can you rely on specific ordering behaviour.
It's not starvation (it's not: Oh no! Thread 2 and 3 are doing all the work and 4 and 5 are just hanging out doing nothing! That's bad - the system could be more efficient!) - because it doesn't matter which thread 'does the work'. A CPU core is a CPU core, it cares not which thread it ends up running.
Starvation is a different principle. Imagine instead of Thread.sleep (which means the threads aren't waiting for anything specific, other than some time to elapse), instead the threads want to print the result of some expensiv-ish math operation. If you just let 2 threads each say 'Hello!', then the impl of System.out says that it would be acceptable for the JVM to produce:
HelHellloo!!
So to prevent this, you use locks to create a 'talking stick' of sorts: A thread only gets to print if it has the talking stick. Each of 5 threads will all perform, in a loop, the following operation:
Do an expensive math operation.
Acquire the talking stick.
Print the result of the operation.
Release the talking stick.
Loop back to the top.
Now imagine that, despite the fact that the math operation is quite expensive, for whatever reason you have an excruciatingly slow terminal, and the 'print the result of the operation' job takes a really long time to finish.
Now you can run into starvation. Imagine this scenario:
Threads 1-5 all do their expensive math simultaneously.
Arbitrarily, thread 4 ends up nabbing the talking stick.
The other 4 threads soon too want the talking stick but they have to wait; t4 has it. They do nothing now. Twiddling their thumbs (they could be calculating, but they are not!)
after the excruciatingly long time, 4 is done and releases the stick. 1, 2, 3, and 5 dogpile on like its the All-Blacks and 2 so happens to win the scrum and crawls out of the pile with the stick. 1, 3, and 5 gnash their teeth and go back yet again to waiting for the stick, still not doing any work. Whilst 2 is busy spending the really long time printing results, 4 goes back to the top of the loop and calculates another result. It ends up doing this faster than 2 manages to print, so 4 ends up wanting the talking stick again before 2 is done.
2 is finally done and 1, 3, 4, and 5 all scrum into a pile again. 4 happens to get the stick - java makes absolutely no guarantees about fairness, any one of them can get it, there is also no guarantee of randomness or lack thereof. A JVM is not broken if 4 is destined to win this fight.
Repeat ad nauseam. 2 and 4 keep trading the stick back and forth. 1, 3, and 5 never get to talk.
The above is, as per the JMM, valid - a JVM is not broken if it behaves like this (it would be a tad weird). Any bugs filed about this behaviour would be denied: The lock isn't so-called "fair". Java has fair locks if you want them - in the java.util.concurrent package. Fair locks incur some slight extra bookkeeping cost, the assumption made by the synchronized and wait/notify system is that you don't want to pay this extra cost.
A better solution to the above scenario is possibly to make a 6th thread that JUST prints, with 5 threads JUST filling a buffer, at least then the 'print' part is left to a single thread and that might be faster. But mostly, the bottleneck in this getup is simply that printing - the code has zero benefit from being multicore (just having ONE thread do ONE math calculation, print it, do another, and so forth would be better. Or possibly 2 threads: Whilst printing, the other thread calculates a number, but there's no point in having more than one; even a single thread can calculate faster than results can be printed). Thus in some ways this is just what the situation honestly requires: This hypothetical scenario still prints as fast as it can. IF you need the printing to be 'fair' (and who says that? It's not intrinsic to the problem description that fairness is a requirement. Maybe all the various calculations are equally useful so it doesn't matter that one thread gets to print more than others; let's say its bitcoin miners, generating a random number and checking if that results in a hash with the requisite 7 zeroes at the end or whatever bitcoin is up to now - who cares that one thread gets more time than another? A 'fair' system is no more likely to successfully mine a block).
Thus, 'fairness' is something you need to explicitly determine you actually need. If you do, AND starvation is an issue, use a fair lock. new ReentrantLock(true) is all you need (that boolean parameter is the fair parameter - true means you want fairness).
I am trying to learn concurrency in Java, but whatever I do, 2 threads run in serial, not parallel, so I am not able to replicate common concurrency issues explained in tutorials (like thread interference and memory consistency errors). Sample code:
public class Synchronization {
static int v;
public static void main(String[] args) {
Runnable r0 = () -> {
for (int i = 0; i < 10; i++) {
Synchronization.v++;
System.out.println(v);
}
};
Runnable r1 = () -> {
for (int i = 0; i < 10; i++) {
Synchronization.v--;
System.out.println(v);
}
};
Thread t0 = new Thread(r0);
Thread t1 = new Thread(r1);
t0.start();
t1.start();
}
}
This always give me a result starting from 1 and ending with 0 (whatever the loop length is). For example, the code above gives me every time:
1
2
3
4
5
6
7
8
9
10
9
8
7
6
5
4
3
2
1
0
Sometimes, the second thread starts first and the results are the same but negative, so it is still running in serial.
Tried in both Intellij and Eclipse with identical results. CPU has 2 cores if it matters.
UPDATE: it finally became reproducible with huge loops (starting from 1_000_000), though still not every time and just with small amount of final discrepancy. Also seems like making operations in loops "heavier", like printing thread name makes it more reproducible as well. Manually adding sleep to thread also works, but it makes experiment less cleaner, so to say. The reason doesn't seems to be that first loop finishes before the second starts, because I see both loops printing to console while continuing operating and still giving me 0 at the end. The reasons seems more like a thread race for same variable. I will dig deeper into that, thanks.
Seems like first started thread just never give a chance to second in Thread Race to take a variable/second one just never have a time to even start (couldn't say for sure), so the second almost* always will be waiting until first loop will be finished.
Some heavy operation will mix the result:
TimeUnit.MILLISECONDS.sleep(100);
*it is not always true, but you are was lucky in your tests
Starting a thread is heavyweight operation, meaning that it will take some time to perform. Due that fact, by the time you start second thread, first is finished.
The reasoning why sometimes it is in "revert order" is due how thread scheduler works. By the specs there are not guarantees about thread execution order - having that in mind, we know that it is possible for second thread to run first (and finish)
Increase iteration count to something meaningful like 10000 and see what will happen then.
This is called lucky timing as per Brian Goetz (Author of Java Concurrency In Practice). Since there is no synchronization to the static variable v it is clear that this class is not thread-safe.
class Runner extends Thread{
public void run(){
for(int i=0;i<5;i++)
{
System.out.println("Counting "+i);
}
}
}
public class App {
public static void main(String args[])
{
Runner runner1=new Runner();
runner1.start();
Runner runner2=new Runner();
runner2.start();
}
}
I was just going through the basics of threads in java. The expected output is :
Counting 0
Counting 0
Counting 1
Counting 1
Counting 2
Counting 2
Counting 3
Counting 3
Counting 4
Counting 4
But am getting an output like this cant seem to reason this out:
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
Without any kind of synchronization, there can be no expectation to the order of execution (and interleaving of instructions) for multiple threads.
In your example, you could get your expected output by putting long pauses (Thread.sleep) into each iteration of the loop (still technically not guaranteed, but practically speaking unavoidable).
Please provide Thread sleep in your code. It will run concurrently between both the threads.
System.out.println("counting"+i)
Thread.sleep(500)
Please Insert these code in the run method.IT will work as you want
What I need to do is use a FixedThreadPool of size 3 and then use it to print the ThreadName and then make it go to sleep for a random amount of time within a specified time interval and print that it is awake when it is done. I need to do it thread by thread but my output is coming with all the 3 threads together.
Desired output:
pool-1-thread-1 Going to sleep for random amount of time interval between 800 ms and 1000ms
pool-1-thread-1 done sleeping
pool-1-thread-2 Going to sleep for random amount of time interval between 800 ms and 1000ms
pool-1-thread-2 done sleeping
pool-1-thread-3 Going to sleep for random amount of time interval between 800 ms and 1000ms
pool-1-thread-3 done sleeping
I need to use FixedThreadPool only
import java.util.Random;
import java.util.concurrent.*;
class Sleep implements Runnable
{
public void run()
{
Random ran = new Random();
int randomnumber = ran.nextInt(1000-800+1)+800;
System.out.print(Thread.currentThread().getName()+" ");
System.out.println("Going to sleep for random amount of time interval between 800 ms and 1000ms");
try
{
Thread.sleep(randomnumber);
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" done sleeping");
Thread.yield();
}
}
public class Ch6Ex3
{
public static void main(String[] args)
{
ExecutorService exe = Executors.newFixedThreadPool(3);
for(int i=0;i<3;i++)
{
exe.execute(new Sleep());
}
exe.shutdown();
}
}
Create thread pool with only 1 thread. If you use 3 threads then up to 3 runnable can be run concurrently and it's not what you want. So use:
ExecutorService exe = Executors.newFixedThreadPool(1);
Actually better option will be to use newSingleThreadExecutor because it explicitly shows that it runs only 1 runnable at any given time:
ExecutorService exe = Executors.newSingleThreadExecutor();
Internally both methods create ThreadPoolExecutor with 1 thread so there is no actual difference between them only in naming.
If you're creating the objects immediately after one another (within the same ms), they'll probably have the same seed in their Random instances - therefore they'll sleep for the same amount of time.
From javadoc:
Creates a new random number generator. Its seed is initialized to a value based on the current time:
public Random() { this(System.currentTimeMillis()); }
Two Random objects created within the same millisecond will have the same sequence of random numbers.
Besides that there's a problem in your code.
Thread.yield();
is redundant.
If you need that to execute one by one you don't need thread pool. You may just invoke Sleep#run from within your for loop creating different instances of Sleep class.
If you need that to work using FixedThreadPool and you wanna exactly 3 separate threads done your work you should use Locks. Like this: First thread is locking your Lock on entrance and unlocking on exit. Next threads will wait for Lock to relase and do the same stuff.
Read more here:
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html
In an effort to learn about synchronization via Java, I'm just messing around with some simple things like creating a counter shared between threads.
The problem I've run into is that I can't figure out how to print the counter sequentially 100% of the time.
int counterValue = this.counter.incrementAndGet();
System.out.println(this.threadName + ": " + counterValue);
The above increments the AtomicInteger counter, gets the new value, and prints it to the console identified by the thread name that is responsible for that update. The problem occurs when it appears that the incrementAndGet() method is causing the JVM to context switch to another thread for its updates before printing the current thread's updated value. This means that the value gets incremented but not printed until the thread returns to the executing state. This is obvious when looking at this example output:
Thread 3: 4034
Thread 3: 4035
Thread 3: 4036
Thread 1: 3944
Thread 1: 4037
Thread 1: 4039
Thread 1: 4040
Thread 2: 3863
Thread 1: 4041
Thread 1: 4043
You can see that when execution returns to Thread 1, it prints its value and continues updating. The same is evident with Thread 2.
I have a feeling that I'm missing something very obvious.
The problem occurs when it appears that the incrementAndGet() method is causing the JVM to context switch to another thread for its updates before printing the current thread's updated value
This is a race condition that often can happen in these situations. Although the AtomicInteger counters are being incremented properly, there is nothing to stop Thread 2 from being swapped out after the increment happens and before the println is called.
int counterValue = this.counter.incrementAndGet();
// there is nothing stopping a context switch here
System.out.println(this.threadName + ": " + counterValue);
If you want to print the "counter sequentially 100% of the time" you are going to have to synchronize on a lock around both the increment and the println call. Of course if you do that then the AtomicInteger is wasted.
synchronized (counter) {
System.out.println(this.threadName + ": " + counter.incrementAndGet());
}
If you edit your question to explain why you need the output to be sequential maybe there is a better solution that doesn't have this race condition.
You need to synchronize the whole construction for that:
synchronized(this) {
int counterValue = this.counter.incrementAndGet();
System.out.println(this.threadName + ": " + counterValue);
}
In this case, though, you don't have to use AtomicInteger. Plain int would work (counter++).
To print sequentially, the incAndGet and the println must both be in a critical region, a piece of code only one thread may enter, the others being blocked. Realisable with a binary semaphore, for instance, like java synchronized.
You could turn things on the head, and have one thread incrementing a counter and printing it. Other threads may in a "critical region" take only one after another the counter. That would be more efficient, as critical regions should remain small and preferable do no I/O.