I have two threads doing calculation on a common variable "n", one thread increase "n" each time, another decrease "n" each time, when I am not using volatile keyword on this variable, something I cannot understand happens, sb there please help explain, the snippet is like follow:
public class TwoThreads {
private static int n = 0;
private static int called = 0;
public static void main(String[] args) {
for (int i = 0; i < 1000; i++) {
n = 0;
called = 0;
TwoThreads two = new TwoThreads();
Inc inc = two.new Inc();
Dec dec = two.new Dec();
Thread t = new Thread(inc);
t.start();
t = new Thread(dec);
t.start();
while (called != 2) {
//System.out.println("----");
}
System.out.println(n);
}
}
private synchronized void inc() {
n++;
called++;
}
private synchronized void dec() {
n--;
called++;
}
class Inc implements Runnable {
#Override
public void run() {
inc();
}
}
class Dec implements Runnable {
#Override
public void run() {
dec();
}
}
}
1) What I am expecting is "n=0,called=2" after execution, but chances are the main thread can be blocked in the while loop;
2) But when I uncomment this line, the program when as expected:
//System.out.println("----");
3) I know I should use "volatile" on "called", but I cannot explain why the above happens;
4) "called" is "read and load" in working memory of specific thread, but why it's not "store and write" back into main thread after "long" while loop, if it's not, why a simple "print" line can make such a difference
You have synchronized writing of data (in inc and dec), but not reading of data (in main). BOTH should be synchronized to get predictable effects. Otherwise, chances are that main never "sees" the changes done by inc and dec.
You don't know where exactly called++ will be executed, your main thread will continue to born new threads which will make mutual exclusion, I mean only one thread can make called++ in each time because methods are synchronized, and you don't know each exactly thread will be it. May be two times will performed n++ or n--, you don't know this, may be ten times will performed n++ while main thread reach your condition.
and try to read about data race
while (called != 2) {
//System.out.println("----");
}
//.. place for data race, n can be changed
System.out.println(n);
You need to synchronize access to called here:
while (called != 2) {
//System.out.println("----");
}
I sugest to add getCalled method
private synchronized int getCalled() {
return called;
}
and replace called != 2 with getCalled() != 2
If you interested in why this problem occure you can read about visibility in context of java memory model.
Related
This question already has answers here:
How threads are executed in the memory?
(2 answers)
Closed 2 years ago.
This is a simplified version of the problem. Given n number of threads, each printing a constant number all the time. For example, Thread-1 should always print 1, Thread-2 should always print 2 and so on...
How to ensure, the threads are executed in order i.e. the output should be as below:
Thread-1: 1
Thread-2: 2
Thread-3: 3
.
.
.
Thread-n: n
I have a naïve solution to do it through wait()/notify() but I guess there might be a better solution than that. Perhaps, using Semaphore maybe? I don't know.
Update:
Based on the answers received, I think I was not very clear. There are some constraints:
All threads should start at once (assume we don't really have control on that)
Once all the threads start, there should be some sort of communication between the threads to execute in order.
This sequentially execution of thread can be handled beautifully using Thread.join() method. To handle it properly, you may have to create MyRunnable(or, use any name you prefer) which implements Runnable interface. Inside MyRunnable, you can inject a parent Thread, and call parent.join() at top of MyRunnable.run() method. The code is given below:
public class SequentialThreadsTest {
static class MyRunnable implements Runnable {
static int objCount; // to keep count of sequential object
private int objNum;
private Thread parent; // keep track of parent thread
MyRunnable(Thread parent) {
this.parent = parent;
this.objNum = objCount + 1;
objCount += 1;
}
#Override
public void run() {
try {
if(parent != null) {
parent.join();
}
System.out.println("Thread-" + objNum + ": " + objNum);
} catch(InterruptedException e) {
e.printStackTrace();
// do something else
} finally {
// do what you need to do when thread execution is finished
}
}
}
public static void main(String[] args) {
int n = 10;
Thread parentThread = null;
for(int i=0; i<n; i++) {
Thread thread = new Thread(new MyRunnable(parentThread));
thread.start();
parentThread = thread;
}
}
}
And the output is:
Thread-1: 1
Thread-2: 2
Thread-3: 3
Thread-4: 4
Thread-5: 5
Thread-6: 6
Thread-7: 7
Thread-8: 8
Thread-9: 9
Thread-10: 10
You haven't specified many details, but if you only want serializable thread execution you can wait for previous thread to finish and then print. Something like this:
public static void main(String[] args) {
Thread thread = null;
for (int i = 0; i < 10; i++) {
int index = i;
Thread previousThread = thread;
thread = new Thread(() -> {
if (previousThread != null) {
try {
previousThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(index);
});
thread.start();
}
}
Try making a queue - this will do exactly what you want. Simply change the value of n to however many threads you have, and add all the threads sequentially (only once). If ever you want to stop the threads from executing, all you have to do is add end to the queue. Obviously, for a larger project, you will need to modify this code a little bit (I would recommend replacing the main method with a class initializer and pass the LinkedBlockingQueue as a pre-built argument)
import java.util.concurrent.LinkedBlockingQueue;
public class HelloWorld{
private static int n = 2;
private static LinkedBlockingQueue<Thread> queue = new LinkedBlockingQueue<>(n+1);
static Thread a = new Thread(()->{
System.out.print("a");
});
static Thread b = new Thread(()->{
System.out.print("b");
});
static Thread end = new Thread(()->{
break_ = true;
});
public static final int END = 20;//this and the counter are just here so the code doesn't run forever
public static volatile int i = 0;
public static volatile boolean break_ = false;
public static void main(String []args){
queue.add(a);
queue.add(b);
//queue.add(end);
outerloop:
while(true){
Thread toBeRun = queue.poll();
try{
toBeRun.run();
queue.add(toBeRun);
i++;
if(i>=END || break_){//i>=END does not need to be here, it's just to stop it from running forever in this example
break;
}
}catch(NullPointerException e){
break;
}
}
}
}
Note: This uses java 8 lambdas. If you're using an older version of java, you will need to create the threads using the run method.
edit: 1.) Why is "globalCounter" synchronized , but not "Thread.currentThread().getId()"
2.) Can I assign a calculation to each thread? how? Can i work with the results?
public class Hauptprogramm {
public static final int MAX_THREADS = 10;
public static int globalCounter;
public static Integer syncObject = new Integer(0);
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(MAX_THREADS);
for (int i = 0; i < MAX_THREADS; i++) {
threadPool.submit(new Runnable() {
public void run() {
synchronized (syncObject) {
globalCounter++;
System.out.println(globalCounter);
System.out.println(Thread.currentThread().getId());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
}
}
}});
}
threadPool.shutdown();
}
}
1.) Why is "globalCounter" synchronized , but not "Thread.currentThread().getId()"
I can answer why globalCounter is synchronized. To avoid data race and race condition.
In case if it is not synchronized - globalCounter++ computation is a three step process (Read-Modify-Write) -
Read the current value of globalCounter varaible.
Modify its value.
Write/ Assign the modified value back to the globalCounter.
In the absence of synchronization in multi threaded environment, there is a possibility that a thread might read/ modifies the value of globalCounter when another thread is in the mid of this 3 step process.
This can result into thread/s reading stale values or loss of update count.
2) Can I assign a calculation to each thread? how? Can i work with the results?
This is possible. You can look into Future/ FutureTask to work with the result
I am taking a book to do some mock test, I have found this question:
import java.util.concurrent.atomic.AtomicInteger;
class AtomicVariableTest {
private static AtomicInteger counter = new AtomicInteger(0);
static class Decrementer extends Thread {
public void run() {
counter.decrementAndGet(); // #1
}
}
static class Incrementer extends Thread {
public void run() {
counter.incrementAndGet(); // #2
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new Incrementer().start();
new Decrementer().start();
}
System.out.println(counter);
}
}
The answer:
This program will always print 0.
But I think there is no guarantee that the threads will have completed when it prints the counter value.
I mean, most of the time it will return 0, but if you are strict with the theory there is no guarantee of this.
Am I correct?
There is guaranteed. And there is not guaranteed. There is no middle ground.
In this case there is no guarantee that the result is always zero. This is because the threads are not joined - and might never even have actually ran before the print!
For example, among other permutations, the sequence this code could have executed is:
counter.decrementAndGet(); // #1
System.out.println(counter); // Main thread
counter.incrementAndGet(); // #2
// (and so on, at some arbitrary point after the print)
Avoiding such undesired interleaving/execution is handled in Java (as per the JLS) under happens-before relationships.
If the threads were joined (to the thread with the print) then a happens-before would have been established - in this case that would mean that the threads started and finished running - and the result would be guarantee to be zero.
public static void main(String[] args) {
final List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 5; i++) {
final new Incrementer i = new Incrementer();
threads.add(i);
i.start();
final new Decrementer d = new Decrementer();
threads.add(d);
d.start();
}
for (final Thread t : threads) { t.join(); }
System.out.println(counter);
}
See one of the many duplicates: Wait until child threads completed : Java
And this is why you use the ExecutorService or ExecutorCompletionService and never deal with thread management manually because it is extremely error prone otherwise.
How can I adjust fairness between given k threads to generate some output?
In other words imagine we have k threads printing "1" and n threads printing "2".
Now how can we put fairness between threads so each thread print(for example "1") as much as other (k - 1) print(for example "1").and the same for n thread printing "2".
Before you create the threads, create an array[0..numThreads-1] of empty semaphores, one for each thread you are going to create. Signal to each thread on its creation an incrementing semaphore index, 0..numThreads-1.
In the thread function, have it wait on its semaphore[index], then print something, then signal the [(index+1) mod numThreads] semaphore, then loop round to wait on the semaphore[index] again.
Once you have done that, nothing should happen at all.
Throw in one semaphore unit, anywhere.
well, I understand a little, you could make that a thread print a number if you send that number to their constructor.
for example:
public class MyThread extends Thread
{
int number = 0;
public MyThread(int number) {
this.number = number;
}
#Override
public void run()
{
while(true) {
System.out.println(this.number);
this.sleep(1000);//control exception
}
}
}
then in your main
public class Main() {
public static void main(String[] args) {
int k = 10
for(int i = 0; i < k; k++) {
MyThread mt = new MyThread(1);
mt.start();
mt.join();
}
}
}
You should repeat a similar form for Thread printing 2
This isn't homework for me, it's a task given to students from some university. I'm interested in the solution out of personal interest.
The task is to create a class (Calc) which holds an integer. The two methods add and mul should add to or multiply this integer.
Two threads are set-up simultaneously. One thread should call c.add(3) ten times, the other one should call c.mul(3) ten times (on the same Calc-object of course).
The Calc class should make sure that the operations are done alternatingly ( add, mul, add, mul, add, mul, ..).
I haven't worked with concurrency related problems a lot - even less with Java. I've come up with the following implementation for Calc:
class Calc{
private int sum = 0;
//Is volatile actually needed? Or is bool atomic by default? Or it's read operation, at least.
private volatile bool b = true;
public void add(int i){
while(!b){}
synchronized(this){
sum += i;
b = true;
}
}
public void mul(int i){
while(b){}
synchronized(this){
sum *= i;
b = false;
}
}
}
I'd like to know if I'm on the right track here. And there's surely a more elegant way to the while(b) part.
I'd like to hear your guys' thoughts.
PS: The methods' signature mustn't be changed. Apart from that I'm not restricted.
Try using the Lock interface:
class Calc {
private int sum = 0;
final Lock lock = new ReentrantLock();
final Condition addition = lock.newCondition();
final Condition multiplication = lock.newCondition();
public void add(int i){
lock.lock();
try {
if(sum != 0) {
multiplication.await();
}
sum += i;
addition.signal();
}
finally {
lock.unlock();
}
}
public void mul(int i){
lock.lock();
try {
addition.await();
sum *= i;
multiplication.signal();
} finally {
lock.unlock();
}
}
}
The lock works like your synchronized blocks. But the methods will wait at .await() if another thread holds the lock until .signal() is called.
What you did is a busy loop: you're running a loop which only stops when a variable changes. This is a bad technique because it makes the CPU very busy, instead of simple making the thread wait until the flag is changed.
I would use two semaphores: one for multiply, and one for add. add must acquire the addSemaphore before adding, and releases a permit to the multiplySemaphore when it's done, and vice-versa.
private Semaphore addSemaphore = new Semaphore(1);
private Semaphore multiplySemaphore = new Semaphore(0);
public void add(int i) {
try {
addSemaphore.acquire();
sum += i;
multiplySemaphore.release();
}
catch (InterrupedException e) {
Thread.currentThread().interrupt();
}
}
public void mul(int i) {
try {
multiplySemaphore.acquire();
sum *= i;
addSemaphore.release();
}
catch (InterrupedException e) {
Thread.currentThread().interrupt();
}
}
As others have said, the volatile in your solution is required. Also, your solution spin-waits, which can waste quite a lot of CPU cycles. That said, I can't see any problems as far as correctness in concerned.
I personally would implement this with a pair of semaphores:
private final Semaphore semAdd = new Semaphore(1);
private final Semaphore semMul = new Semaphore(0);
private int sum = 0;
public void add(int i) throws InterruptedException {
semAdd.acquire();
sum += i;
semMul.release();
}
public void mul(int i) throws InterruptedException {
semMul.acquire();
sum *= i;
semAdd.release();
}
volatile is needed otherwise the optimizer might optimize the loop to if(b)while(true){}
but you can do this with wait and notify
public void add(int i){
synchronized(this){
while(!b){try{wait();}catch(InterruptedException e){}}//swallowing is not recommended log or reset the flag
sum += i;
b = true;
notify();
}
}
public void mul(int i){
synchronized(this){
while(b){try{wait();}catch(InterruptedException e){}}
sum *= i;
b = false;
notify();
}
}
however in this case (b checked inside the sync block) volatile is not needed
Yes, volatile is needed, not because an assignment from a boolean to another is not atomic, but to prevent the caching of the variable such that its updated value is not visible to the other threads who are reading it. Also sum should be volatile if you care about the final result.
Having said this, it would probably be more elegant to use wait and notify to create this interleaving effect.
class Calc{
private int sum = 0;
private Object event1 = new Object();
private Object event2 = new Object();
public void initiate() {
synchronized(event1){
event1.notify();
}
}
public void add(int i){
synchronized(event1) {
event1.wait();
}
sum += i;
synchronized(event2){
event2.notify();
}
}
public void mul(int i){
synchronized(event2) {
event2.wait();
}
sum *= i;
synchronized(event1){
event1.notify();
}
}
}
Then after you start both threads, call initiate to release the first thread.
Hmmm. There are a number of problems with your solution. First, volatile isn't required for atomicity but for visibility. I won't go into this here, but you can read more about the Java memory model. (And yes, boolean is atomic, but it's irrelevant here). Besides, if you access variables only inside synchronized blocks then they don't have to be volatile.
Now, I assume that it's by accident, but your b variable is not accessed only inside synchronized blocks, and it happens to be volatile, so actually your solution would work, but it's neither idiomatic nor recommended, because you're waiting for b to change inside a busy loop. You're burning CPU cycles for nothing (this is what we call a spin-lock, and it may be useful sometimes).
An idiomatic solution would look like this:
class Code {
private int sum = 0;
private boolean nextAdd = true;
public synchronized void add(int i) throws InterruptedException {
while(!nextAdd )
wait();
sum += i;
nextAdd = false;
notify();
}
public synchronized void mul(int i) throws InterruptedException {
while(nextAdd)
wait();
sum *= i;
nextAdd = true;
notify();
}
}
The program is fully thread safe:
The boolean flag is set to volatile, so the JVM knows not to cache values and to keep write-access to one thread at a time.
The two critical sections locks on the current object, which means only one thread will have access at a time. Note that if a thread is inside the synchronized block, no thread can be in any other critical sections.
The above will apply to every instance of the class. For example if two instances are created, threads will be able to enter multiple critical sections at a time, but will be limited to one thread per instances, per critical section. Does that make sense?