This question already has answers here:
Why is i++ not atomic?
(10 answers)
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 4 years ago.
I wanted to test out multithreading for a project of mine, trying to also develop a solution in case something goes wrong.
So I made this small test:
main
public class main
{
static int addToCounter;
static int addToErrorCounter;
public static void main(String[] args) throws InterruptedException
{
int threads = 10;
Executor exec = new Executor();
for (int i = 0; i < threads; i++)
{
double error = Math.random();
testClass aldo = new testClass();
Thread thread = aldo.getThread(300, error);
exec.execute(thread);
}
while (threads != (addToCounter + addToErrorCounter))
{
System.out.println("Not all threads finished, number of finished threads is: " + (addToCounter + addToErrorCounter));
Thread.sleep(50);
}
System.out.println("Number of Threads that finished correctly: " + addToCounter);
}
}
testClass
import test1.main;
public class testClass
{
public Thread getThread(long time, double error)
{
Thread thread = new Thread()
{
public void run()
{
try
{
Thread.sleep(time);
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if (error > 0.5)
{
main.addToErrorCounter++;
throw new java.lang.Error("HELLO");
}
System.out.println("I DID THIS!");
main.addToCounter++;
}
};
return thread;
}
}
(you'll have to fix the imports, also I use a custom class Executor, although that's only a wrapper for ExecutorService)
The weird behaviour is that sometimes it works properly, and sometimes it doesn't (total terminated thread count is 9, although I can see clearly it printed "I DID THIS!" and the error exactly 10 times).
Any fix?
The Problem might be a racecondition.
the "++" operator is not atomic.
Imageine the following scenario. There are two Threads at the same time. both want to increase a number and finish.
The initial value of the number is 0.
Thread 0 reads the number, knows now it is 0.
Thread 1 reads the number, knows now it is 0.
Thread 0 (who knew it was 0) now writes 1 to the memory.
Thread 1 does not know, that the number has changed, and still believes the number is 0 so he also writes a 1 to the memory.
You need something like a synchronizing mechanisim, something like a lock, or a semaphore or something else.
have a look at this for more information: http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/
for your example you could use the "synchronized" example from that link.
add a method to your main class looking like this to increment the addToCounter and also to the addToErrorCounterto remove the effects from your error counter:
synchronized AddToError(int e){
addToError += e;
}
synchronized IncCounter(){
addToCounter++;
}
call those methods in your threads in the testclass instead of incrementing them unsynchronized.
My guess is that the postfix operator (main.addToCounter++) is not atomic. This line of code is probably equivalent to something like:
int temp = main.addToCounter;
main.addToCounter = temp + 1;
return temp;
With multiple threads doin this at the same time, two threads could obtain the same value for temp (because both peform the first line in the above pseudo-code before either performs the second), and hence the counter total will be too small once all threads are complete. See Why is i++ not atomic? for more information.
A quick fix in this situation is to make addToCounter an AtomicInteger, then use addToCounter.incrementAndGet() in place of addToCounter++.
Related
There is a thread calculating prime numbers and adding them into a collection.
Now there are other Threads which will perform a bool isPrime(long n) method. This method will just look into the collection if it contains the number (n).
But the thread performing isPrime(...) needs to wait until:
the number was added
there is a number greater than n so I know n can't be prime.
And its only allowed to notify the thread in this cases. So I can't notify after every number added to the collection and check if its the number or higher.
Can you just give me some explanation about this waiting for conditions without busy waiting?
I just know that I can make threads wait on objects and other threads can notify them but i just cant get my head around this behavior, maybe I just think in a wrong way.
This really depends on your overall design.
A simple solution would work like this:
you have 1 thread prime-generator and n threads prime-testers
initially all prime-testers call wait()
every time prime-generator adds a new prime, it notifies all prime-testers
each testers checks if its number (or a larger one) is already in, if the tester either found its number, or knows "not in". If not, it calls wait() again.
The great advantage of that solution: the prime-generator doesn't need to know about how many prime-testers exist. It just notifies all threads waiting on a common monitor.
Alternatively, the prime-generator could know exactly which prime-testers exist, and also, what number they are responsible for. So instead of waking up all testers, it would notify only that one that needs to know.
Please understand: you only gave some vague requirements, without any code. Thus you receive a somehow vague answer, without any code. My answer is meant as inspiration to guide your next steps in your homework.
And just for the record: if you want to go for really large prime numbers, then using a list is a bad choice. Assume your list contains 1 million primes. The cost for calling contains() will grow linear with the number of entries. So rather use a collection that allows for quick finding of elements (some sort of set/tree), but also for quick access to the currently "last" (largest) number in the collection.
The basic idea from the answer by #GhostCat turned into code:
import java.util.HashSet;
import java.util.Set;
public class PrimeThreading {
// All prime numbers found so far.
private static final Set<Long> primes = new HashSet<>();
// Last number checked by the generator.
private static long numbersChecked = 0L;
// The lock object.
private static final Object lock = new Object();
private static class PrimeGenerator implements Runnable {
private final long maxNumber = Long.MAX_VALUE;
#Override
public void run() {
// Generate all prime numbers from 2 to maxNumber
for (long n = 2; n < maxNumber; n++) {
// Naively test if n is prime.
boolean isPrime = true;
for (long i = 2; i * i < n; i++) {
if (n % i == 0) {
isPrime = false;
break;
}
}
synchronized (lock) {
if (isPrime) {
primes.add(n);
}
numbersChecked = n;
// Notify waiting threads
lock.notifyAll();
}
}
}
}
private static boolean isPrime(long x) {
synchronized (lock) {
// Wait until number checked is greater than x
while (x > numbersChecked) {
try {
lock.wait();
} catch (InterruptedException e) {
break;
}
}
return primes.contains(x);
}
}
public static void main(String[] args) {
Thread thread = new Thread(new PrimeGenerator());
thread.setDaemon(true);
thread.start();
System.out.println(isPrime(15_485_863));
}
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
So I was just messing around with basic concurrency when I noticed the empty synchronized block shown in the program causes the outputs to sync up. There is nothing in the block, so why does it do this?
public class MainClass {
public static void main(String[] args) throws InterruptedException {
SyncTest f = new SyncTest();
f.start();
for (int i = 0; i < 20; i++) {
System.out.println("MAIN THREAD:" + i);
Thread.sleep(500);
synchronized (f) {
for (int t = 0; t < 15; t++) {
Thread.sleep(100);
}
}
}
}
}
class SyncTest extends Thread {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
System.out.println("OTHER THREAD: " + i);
Thread.sleep(1300);
synchronized (this) {} //Why does this have an effect on the output when commented?
} catch (InterruptedException ex) {}
}
}
}
The mechanics of the synchronized can be summed up like this
synchronized(f) { //wait for no-one use f
// do some stuff
//nobdy can use f during this time
} //free f, other can use it
It basically act like if you used a lock, where the lock is f
So even if your block does nothing than waiting, during this wait time f is not available. So it will synchronize your program even if there's only a wait in your block
The execution flow will not enter a synchronized block if the specified lock has already been taken by another thread. This is always the case, even if the synchronized block contains no code at all.
The locks in your example are the same object (the instance of SyncTest.) So while the non-empty synchronized block is running, the empty one will be waiting for it to complete. In this case, because of the way the Thread.sleep() calls line up, it just so happens that the outputs are reasonably likely to be synchronized as a result.
You've got synchronized 2 times by the same object.
First time in the MainClass:
SyncTest f = new SyncTest();
synchronized (f) {...}
Second time in the SyncTest instance itself by "this":
synchronized (this) {}
There are 2 threads in your program: main thread and thread of SyncTest.
Each thread comes to the point of synchronization by SyncTest object and waits until another thread will go out of the synchronization section.
Berry's answer summarizes what synchronized does and mentions that the content of the block does not matter. So the question is not really why the behavior changes, but why it changes so drasticly.
Your threads "sync up" (i.e. log one by one even though otherThread should be a bit faster and sometimes log twice before mainThread) because your mainThread sleeps for a solid 1500ms when blocking the sync object:
synchronized (f)
{
for (int t = 0; t < 15; t++) // this is
{ // (roughly)
Thread.sleep(100); // equivalent to
} // Thread.sleep(1500);
}
That means that mainThread doesn't give otherThread a chance use its speed advantage (1300 ms vs. 1500ms) and makes it wait until it is done sleeping. Change that piece of code to
for (int t = 0; t < 15; t++)
{
synchronized (f)
{
Thread.sleep(100);
}
}
and otherThread will slide right into one of those breaks between the 100ms naps and the empty sync block is not affecting anything much anymore.
Note that the empty sync block still has a little effect and might change the order of the logs a bit because otherThread might still have to wait a little (but only a maximum 100ms instead of 1500ms). It won't result in such a strict back-and-fourth anymore, though.
I have seen the example of PingPong using synchronized keyword.Basicly the actual example is this:
public class PingPong implements Runnable {
synchronized void hit(long n) throws InterruptedException {
for (int i = 1; i < 3; i++)
System.out.print(n + "-" + i + " ");
}
public static void main(String[] args) {
new Thread(new PingPong()).start();
new Thread(new PingPong()).start();
}
public void run() {
try {
Long id = Thread.currentThread().getId();
hit(id);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Normally the hit method is not synchronized because the synchronized keyword will work only if there is one object.So the result can be like 8-1 9-1 8-2 9-2 or 8-1 9-1 9-2 8-2...(It's a randomly result).But in this example it give us all time 8-1 8-2 9-1 9-2 which is a little bit strange because that mean that the hit method is synchronized!!!.
I have modified the code to check again that the hit method must be not sycnhronized so i add a Thread.sleep(1000) at the starting of the hit method it will be like
synchronized void hit(long n) throws InterruptedException {
Thread.sleep(1000);
for (int i = 1; i < 3; i++)
System.out.print(n + "-" + i + " ");
}
Now the code is giving random result each time i make an execution.
I'm really getting confusing!!
Can some one help me in understanding this issue ?
You do indeed have two separate instances of PingPong, which would mean that there would be two separate monitor objects, which should mean that the threads are not being forced to run synchronously.
I think that you are probably running into thread scheduling behavior. On a single core CPU, the code may very well execute as you describe because the thread scheduler is never given a chance to take over.
If you add a sleep to your for loop:
synchronized void hit(long n) throws InterruptedException {
for (int i = 1; i < 3; i++){
System.out.print(n + "-" + i + " ");
Thread.sleep(0);
}
}
That should release the scheduler to run other threads. Note that the JVM doesn't provide any guarantees of how the scheduler will actually behave, but in my experience the above is sufficient.
If you are on a multi-core CPU, I'd expect it to work as you expected without the sleep() call.
Not sure what is meant by synchronization. Do you want to mean that the threads are being picked up by the thread scheduler in a particular order always? If yes, that is not true. Just increase "i" from 3 to a higher value, say 10. I am seeing the following output :
12-1 11-1 12-2 11-2 12-3 11-3 12-4 11-4 12-5 11-5 12-6 11-6 12-7 11-7 12-8 12-9 11-8 11-9
Well, I have multi-core processor, hence multiple threads at the same point of time. I guess that should be the case even for you.
I'm trying to understand synchronization of multiple threads in Java more fully. I understand the high level idea behind the use of the synchronized keyword, and how it provides mutual exclusion among threads.
The only thing is that most of the examples I read online and in my textbook still work correctly even if you remove the synchronized keyword which is making this topic more confusing than I think it needs to be.
Can anyone provide me with a concrete example of when not including the synchronized keyword will produce erroneous results? Any information would be much appreciated.
You can usually trigger a race condition by increasing the number of iterations. Here's a simple example that works with 100 and 1,000 iterations but fails (at least on my quad-core box) at 10,000 iterations (sometimes).
public class Race
{
static final int ITERATIONS = 10000;
static int counter;
public static void main(String[] args) throws InterruptedException {
System.out.println("start");
Thread first = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < ITERATIONS; i++) {
counter++;
}
}
});
Thread second = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < ITERATIONS; i++) {
counter++;
}
}
});
first.start();
second.start();
first.join();
second.join();
System.out.println("Counter " + counter + " should be " + (2 * ITERATIONS));
}
}
>>> Counter 12325 should be 20000
This example fails because access to counter is not properly synchronized. It can fail in two ways, possibly both in the same run:
One thread fails to see that the other has incremented the counter because it doesn't see the new value.
One thread increments the counter between the other thread reading the current value and writing the new value. This is because the increment and decrement operators are not atomic.
The fix for this simple program would be to use an AtomicInteger. Using volatile isn't enough due to the problem with increment, but AtomicInteger provides atomic operations for increment, get-and-set, etc.
The thing about race conditions is that they don't necessarily happen if you don't do proper synchronization -- indeed, quite frequently it'll work just fine -- but then one year later, in the middle of the night, your code will crash with a completely unpredictable bug that you can't reproduce, because the bug only appears randomly.
Race conditions are so insidious precisely because they don't always make your program crash, and they trigger more or less randomly.
public class SieveGenerator{
static int N = 50;
public static void main(String args[]){
int cores = Runtime.getRuntime().availableProcessors();
int f[] = new int[N];
//fill array with 0,1,2...f.length
for(int j=0;j<f.length;j++){
f[j]=j;
}
f[0]=0;f[1]=0;//eliminate these cases
int p=2;
removeNonPrime []t = new removeNonPrime[cores];
for(int i = 0; i < cores; i++){
t[i] = new removeNonPrime(f,p);
}
while(p <= (int)(Math.sqrt(N))){
t[p%cores].start();//problem here because you cannot start a thread which has already started(IllegalThreadStateException)
try{
t[p%cores].join();
}catch(Exception e){}
//get the next prime
p++;
while(p<=(int)(Math.sqrt(N))&&f[p]==0)p++;
}
//count primes
int total = 0;
System.out.println();
for(int j=0; j<f.length;j++){
if(f[j]!=0){
total++;
}
}
System.out.printf("Number of primes up to %d = %d",f.length,total);
}
}
class removeNonPrime extends Thread{
int k;
int arr[];
public removeNonPrime(int arr[], int k){
this.arr = arr;
this.k = k;
}
public void run(){
int j = k*k;
while(j<arr.length){
if(arr[j]%k == 0)arr[j]=0;
j=j+arr[k];
}
}
}
Hi I'm getting an IllegalThreadStateException when I run my code and I've figured it's because I am trying to start a thread that has already been started. So how could I kill
or stop the thread each time, to get around this problem?
how could I kill or stop the thread each time, to get around this problem?
The answer is, you can't. Once started, a Thread may not be restarted. This is clearly documented in the javadoc for Thread. Instead, what you really want to do is new an instance of RemoveNonPrime each time you come around in your loop.
You have a few other problems in your code.
First, you need to increment p before using it again:
for(int i = 0; i < cores; i++){
t[i] = new removeNonPrime(f,p); //<--- BUG, always using p=2 means only multiples of 2 are cleared
}
Second, you might be multithreaded, but you aren't concurrent. The code you have basically only allows one thread to run at a time:
while(p <= (int)(Math.sqrt(N))){
t[p%cores].start();//
try{
t[p%cores].join(); //<--- BUG, only the thread which was just started can be running now
}catch(Exception e){}
//get the next prime
p++;
while(p<=(int)(Math.sqrt(N))&&f[p]==0)p++;
}
Just my $0.02, but what you are trying to do might work, but the logic for selecting the next smallest prime will not always pick a prime, for example if one of the other threads hasn't processed that part of the array yet.
Here is an approach using an ExecutorService, there are some blanks (...) that you will have to fill in:
/* A queue to trick the executor into blocking until a Thread is available when offer is called */
public class SpecialSyncQueue<E> extends SynchronousQueue<E> {
#Override
public boolean offer(E e) {
try {
put(e);
return true;
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
return false;
}
}
}
ExecutorService executor = new ThreadPoolExecutor(cores, cores, new SpecialSyncQueue(), ...);
void pruneNonPrimes() {
//...
while(p <= (int)(Math.sqrt(N))) {
executor.execute(new RemoveNonPrime(f, p));
//get the next prime
p++;
while(p<=(int)(Math.sqrt(N))&&f[p]==0)p++;
}
//count primes
int total = 0;
System.out.println();
for(int j=0; j<f.length;j++){
if(f[j]!=0){
total++;
}
}
System.out.printf("Number of primes up to %d = %d",f.length,total);
}
class RemoveNonPrime extends Runnable {
int k;
int arr[];
public RemoveNonPrime(int arr[], int k){
this.arr = arr;
this.k = k;
}
public void run(){
int j = k*k;
while(j<arr.length){
if(arr[j]%k == 0)arr[j]=0;
j+=k;
}
}
}
You could implement Runnable instead and use new Thread( $Runnable here ).start() or use a ExecutorService to reuse threads.
* It is never legal to start a thread more than once.
* In particular, a thread may not be restarted once it has completed
* execution.
*
* #exception IllegalThreadStateException if the thread was already started
*/
public synchronized void start() {
In Android, document still mention that we will get IllegalThreadStateException if the thread was already started.
However for some device it will not throw this exception (tested on Kyocera 7.0). In some popular device like Samsung, HTC, it throw throw the exception normally
I answer here because the Android question is mark as duplicated to this question.
Why does an IllegalThreadStateException occur when Thread.start is
called again
Because JDK/JVM implementers coded Thread.start() method that way. Its a reasonable functional expectation to be able to restart a thread after a thread has completed its execution and that is what being suggested in chrisbunney's answer ( and I have put in a comment in that answer ) but if you look at Thread.start() implementation , the very first line is ,
if (threadStatus != 0)
throw new IllegalThreadStateException();
where threadStatus == 0 means NEW state so my guess is that implementation doesn't resets this state to zero after execution has completed & thread is left in TERMINATED state ( non - zero state ). So when you create a new Thread instance on same Runnable , you basically reset this state to zero.
Also, I noticed the usage of word - may & never in same paragraph as different behavior is being pointed out by Phan Van Linh on some OSes,
It is never legal to start a thread more than once. In particular, a
thread may not be restarted once it has completed execution.
I guess what they are trying to say in above Javadoc that even if you don't get IllegalThreadStateException on certain OS, its not legal in Java/Thread class way & you might get unexpected behavior.
The famous thread state diagrams depict the same scenario - no going back from dead state to new.
ThreadPools can be used for delivering tasks to set number of threads. When initiating you set the number of threads. Then you add tasks for the pool. And after you can block until all tasks have finished processing. Here is some sample code.
I am not at all sure I understand the question. All the methods for stopping threads that are executed from other threads are deprecated; the way to stop a thread is to have it check a variable that it and another thread can access (perhaps a volatile variable), and have the running thread check it occasionally to see if it should exit on its own.
I cannot tell why/whether you want to eliminate the running thread and use another one, and I cannot see how the different threads are going to help execute your overall goal any faster. But it's possible I'm just not understanding the math.
The Thread.isAlive() method can tell you if the Thread has already been started. Simply do this where you want to start your thread:
if(!t[p%cores].isAlive()){
t[p%cores].start();
}