I have a question about using Semaphores in multithreaded Java code.
There are three threads being fired asynchronously. One of them calls zero(), the other calls even(), and the last one calls odd(). "0102" is the correct output.
Semaphore zero = new Semaphore(1);
Semaphore odd = new Semaphore(0);
Semaphore even = new Semaphore(0);
public void zero(IntConsumer printNumber) throws InterruptedException {
for(int i = 0; i < n; i++) {
zero.acquireInterruptibly();
printNumber.accept(0);
if(i % 2 == 0) {
odd.release();
} else {
even.release();
}
}
}
public void even(IntConsumer printNumber) throws InterruptedException {
for (int i = 2; i <= n; i += 2) {
even.acquire();
printNumber.accept(i);
zero.release();
}
}
public void odd(IntConsumer printNumber) throws InterruptedException {
for (int i = 1; i <= n; i += 2) {
odd.acquire();
printNumber.accept(i);
zero.release();
}
}
In the code shown above, the first function that will run is function 'zero' because only that lock is able to be required. Then, the function 'odd' will be able to be called from another thread since it's lock has been released and therefore able to be acquired.
Two questions:
1) Can the same thread that acquired the 'zero' lock reenter the for loop before the lock has been released by the function 'odd'
2) How is the state of the for loop preserved after a thread has been switched out?
Edit: In understanding semaphores a bit more, I know realize that regardless of whether the fact that the thread had acquired the semaphore before, it can not run unless the number of permits available for that sempaphore is greater than 0. Therefore, until the number of permits available is greater than 0, the function will not be able to run until a release of that semaphore occurs so that the number of permits available is greater than 0. The question remains though, how is that state of the for loop preserved so that when I reenter the for loop, I do not start back at the initial 'i' value.
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));
}
}
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++.
This was an interview question , any help would be appreciated
How do you synchronize two threads, out of which one increments a value and the the other displays it ( P.S. the thread which displays the value must only display a value when its a new value )
Ex : int x = 5;
T1 : increments it to 6
T2 : must display 6 ( only once ) and must display it again when it becomes 7
I answered that I would use a semaphore something like:
int c=0; // variable that I used to synchronize
// In T1
if( c = 0 )
{
c++;
x++; // value that is incremented
}
// in T2
if( c == 1 )
{
cout<<x;
c--;
}
He then asked what would you do if there's a context switch from thread T1 to T2 after setting c to 1 but before incrementing x ( As in that case it would enter P2 before incrementing x )
I couldn't answer this part. Any help would be appreciated.
This is a classic use case for a condition variable with the slight hitch that the value can easily update more than once in thread 1 before thread 2 runs to handle it:
// In some scope common to both threads
int c_ = 0; // variable
std::mutex mutex_();
std::condition_variable cond_();
// Thread 1
{
std::lock_guard<std::mutex> lock(mutex_);
++c_;
}
cond_.notify_one();
// Thread 2
{
std::lock_guard<std::mutex> lock( mutex_ );
int cLocal = c_;
while ( !done ) {
cond_.wait( lock, [] { return c_ != cLocal; } );
while ( cLocal++ < c_ )
... // Display new *local* value
}
}
Nice exercise.
You haven't specified the c++ tag in the question, but the question itself contains cout<<x, so you were probably interviewing for a C++ position. Despite that, I'm going to answer in Java since this is an interview question and language shouldn't matter much as long as I avoid using anything too specific to Java.
As your interviewer pointed out, the synchronization has to happen in both directions:
The printing thread must wait for the incrementing thread to finish its job
The incrementing thread must wait for the printing thread to finish its job
So we need something to let us know that the printer is done (so the incrementer can run), and another to let us know that the incrementer is done. I used two semaphores for that:
Working version on Ideone
import java.util.concurrent.Semaphore;
class IncrementDemo {
static int x = 0;
public static void main(String[] args) {
Semaphore incrementLock = new Semaphore(0);
Semaphore printLock = new Semaphore(0);
Thread incrementer = new Thread(() -> {
for(;;) {
incrementLock.acquire(); //Wait to be allowed to increment
x++;
printLock.release(); //Allow the printer to print
}
});
Thread printer = new Thread(() -> {
for (;;) {
incrementLock.release(); //Let the incrementer to its job
printLock.acquire(); //Wait to be allowed to print
System.out.println(x);
}
});
incrementer.setDaemon(false); //Keep the program alive after main() exits
printer.setDaemon(false);
incrementer.start(); //Start both threads
printer.start();
}
}
(I removed the try/catch blocks around acquire for readability).
Output:
1
2
3
4
5
6
7
...
Problems:
There are 2 main problems with parallel code in general.
1. Atomicity
The smallest granularity in code are in fact not the single operations like i++, but the underlying assembly-instructions. Therefore every operation, which involves a write, may not be called from multiple threads. (this differs heavily on your target architecture, but x86 is in contrast to arm64 very restrictive)
But luckily c++ provides the std::atomic operations, which give you a nice plattform independent way to modify variables from multiple threads.
2. Consistency
Both the compiler and the processor are allowed to reorder any instruction as long the consistency of the local thread is preserved. So what does this mean?
Take a look at your first thread
if( c = 0 )
{
c++;
x++; // value that is incremented
}
You have 3 operations c == 0, c++ and x++. Both increments do not depend from each other, hence the compiler would be allowed to swap them. At runtime the core may reorder them too, leaving you in very vague situation. In a sequential world this is perfectly fine and improves the overall performance (unless it leads to security holes like meltdown). Unfortunately neither the compiler or the cpu recognize parallel code, therefore any optimization may break your parallel program.
But once again, c++ provides a built-in solution for this problem called std::memory_order, which enforces are specific consistency-model.
Solutions:
Simple mutex:
A mutex is a simple, but powerfull tool. It solves the problems with Atomicity and Consistency by providing so called critical sections, which prevent parallel execution. This means, that in the given example the if-clause in both threads are sequential and will never be executed in parallel.
The implementation works, but has a flaw. If one of the threads is very slow, the other one will waste a lot of cpu-time by continous checking the newValue flag.
#include <mutex>
std::mutex mutex;
int value = true;
bool newValue = false;
void producer_thread() {
while(true) {
std::lock_guard<std::mutex> lg(mutex);
if (newValue == false) {
value++;
newValue = true;
}
}
}
void consumer_thread() {
while(true) {
std::lock_guard<std::mutex> lg(mutex);
if (newValue == true) {
std::cout << value;
newValue = false;
}
}
}
Condition Variable:
A condition variable is basically just a "wait-for-notify"-construct. You can block the current execution by calling wait until an other thread calls notify. This implementation would be the go-to scenario.
#include <mutex>
#include <condition_variable>
std::mutex mutex;
std::condition_variable cond;
int value = true;
bool newValue = false;
void producer() {
while(true) {
std::unique_lock<std::mutex> ul(mutex);
while (newValue == true) {
cond.wait(ul);
}
value++;
newValue = true;
cond.notify_all();
}
}
void consumer() {
while(true) {
std::unique_lock<std::mutex> ul(mutex);
while (newValue == false) {
cond.wait(ul);
}
std::cout << value;
newValue = false;
cond.notify_all();
}
}
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();
}