I've been given the task to find the way to share a method's, involved in several threads, local variable, so it's value would be visible for every thread running this method.
Now my code look's like this:
public class SumBarrier2 implements Barrier {
int thread_num; // number of threads to handle
int thread_accessed; // number of threads come up the barrier
volatile int last_sum; // sum to be returned after new lifecyrcle
volatile int sum; // working variable to sum up the values
public SumBarrier2(int thread_num){
this.thread_num = thread_num;
thread_accessed = 0;
last_sum = 0;
sum = 0;
}
public synchronized void addValue(int value){
sum += value;
}
public synchronized void nullValues(){
thread_accessed = 0;
sum = 0;
}
#Override
public synchronized int waitBarrier(int value){
int shared_local_sum;
thread_accessed++;
addValue(value);
if(thread_accessed < thread_num){
// If this is not the last thread
try{
this.wait();
} catch(InterruptedException e){
System.out.println("Exception caught");
}
} else if(thread_num == thread_accessed){
last_sum = sum;
nullValues();
this.notifyAll();
} else if (thread_accessed > thread_num ) {
System.out.println("Something got wrong!");
}
return last_sum;
}
}
So the task is to replace the class member
volatile int last_sum
with method's waitBarrier local variable, so it's value would be visible to all threads.
Any suggestions?
Is it even possible?
Thanks in advance.
In case the variable last_sum is updated by only one thread, then declaring it volatile will work. If not then you should look at AtomicInteger
An int value that may be updated atomically. See the
java.util.concurrent.atomic package specification for description of
the properties of atomic variables. An AtomicInteger is used in
applications such as atomically incremented counters, and cannot be
used as a replacement for an Integer. However, this class does extend
Number to allow uniform access by tools and utilities that deal with
numerically-based classes.
You can have the practical uses of AtomicInteger here: Practical uses for AtomicInteger
Related
I have the following code:
public class CheckIfSame implements Runnable {
private int[][] m;
private int[][] mNew;
private int row;
private boolean same;
public CheckIfSame(int[][] m,int[][] mNew,,int row,boolean same) {
this.m = m;
this.mNew = mNew;
this.row = row;
this.same = same;
}
#Override
public void run() {
for (int i = 0; i < mUpd[0].length; i++) {
if(m[row][i] != mUpd[row][i]) {
same = false;
}
}
}
}
Basically, the idea of this is that I use multi-threading to check row by row, whether the 2 matrices differ by at least 1 element.
I activate these threads through my main class, passing rows to an executor pool.
However, for some reason, the boolean same does not seem to update to false, even if the if condition is satisfied.
Multiple threads are trying to access that boolean at the same time: a race condition while updating the same variable.
Another possible scenario for non-volatile booleans in multithreaded applications is being affected by compiler optimizations - some threads may never notice the changes on the boolean, as the compiler should assume the value didn't change. As a result, until an specific trigger, such as a thread state change, threads may be reading stale/cached data.
You could choose an AtomicBoolean. Use it when you have multiple threads accessing a boolean variable. This will guarantee:
Synchronization.
Visibility of the updates (AtomicBoolean uses a volatile int internally).
For example:
public class CheckIfSame implements Runnable
{
//...
private AtomicBoolean same;
public CheckIfSame(..., AtomicBoolean same)
{
//...
this.same = same;
}
#Override
public void run()
{
for (int i = 0; i < mUpd[0].length; i++)
if(m[row][i] != mUpd[row][i])
same.set(false); // <--race conditions hate this
}
}
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.
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
This question already has answers here:
atomic increment of long variable?
(4 answers)
Why is i++ not atomic?
(10 answers)
Closed 6 years ago.
I'm currently trying to attempting to study concurrency, specifically "volatile" keyword.
By declaring the counter variable volatile all writes to the counter variable will be written back to main memory immediately. Also, all reads of the counter variable will be read directly from main memory. Here is how the volatile declaration of the counter variable looks
and
When a thread writes to a volatile variable, then not just the volatile variable itself is written to main memory. Also all other variables changed by the thread before writing to the volatile variable are also flushed to main memory. When a thread reads a volatile variable it will also read all other variables from main memory which were flushed to main memory together with the volatile variable.
Source : tutorials.jenkov.com | Java Concurrency - Java Volatile Keyword
Which makes me conclude/assume that any change that i make to a volatile variable will always be visible to all thread. So, I make a code to test it.
TestClass
package org.personal.test1;
class TestClass {
public static int w = 0;
public static int x = 0;
public static int y = 0;
public static volatile int z = 0;
private static final int ITERATIONS = 100000;
public static void sooPlus(int indents) {
for (int i = 0; i < TestClass.ITERATIONS; i++) {
TestClass.w++;
TestClass.x++;
TestClass.y++;
TestClass.z++;
}
}
public static void sooMinus(int indents) {
for (int i = 0; i < TestClass.ITERATIONS; i++) {
TestClass.w--;
TestClass.x--;
TestClass.y--;
TestClass.z--;
}
}
public static synchronized String getVariableValues () {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("(");
stringBuilder.append("w : "+TestClass.w+", ");
stringBuilder.append("x : "+TestClass.x+", ");
stringBuilder.append("y : "+TestClass.y+", ");
stringBuilder.append("z : "+TestClass.z+")");
return stringBuilder.toString();
}
}
Main Class
package org.personal.test1;
/**
* <ol type="I">
* <li>
* jenkov.com - Java Volatile Keyword
* </li>
* </ol>
*/
public class Main {
public static void main(String[] args) {
Main.call1();
}
private static void call1() {
Main.test1();
}
private static void test1() {
Thread thread1 = new Thread("Thread1") {
#Override
public void run() {
TestClass.sooPlus(1);
}
};
Thread thread2 = new Thread("Thread2") {
#Override
public void run() {
TestClass.sooMinus(4);
}
};
thread1.start();
thread2.start();
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(TestClass.getVariableValues());
}
}
The results that i get were not what i was expecting.
What i get (varies)
(w : -2314, x : -1692, y : -1416, z : -1656)
What I'm expecting
(w : 0, x : 0, y : 0, z : 0)
or at least
(w : -2314, x : -1692, y : -1416, z : 0)
The Questions
What did I assume/conclude wrong that resulted in a different output than expected?
Was my testing methodology incorrect? If yes, then how can i fix it?
(optional) Are there any good tutorial on Java Concurrency that you recommend?
Notes
I did attempt to read similar questions but i wasn't able to fully understand what the questioner was attempting to do in order to understand his problem.
The volatile keyword provides a weak form of thread safety. It guarantees visibility, but not atomicity or mutual exclusion.
Is it possibile for a volatile field to be not thread safe? Thread safe. Writes to non-volatile double and long values are not atomic, but writes to volatile double and long variables are.
Is it possible for a class made up of all volatile fields to be not thread safe? Yes, if writes to the fields cause invalid state transitions (by lack of synchronization).
(optional) Are there any good tutorial on Java Concurrency that you
recommend?
The book that is usually recommended as the authoritative treatment of this subject is "Java Concurrency in Practice" by Brian Goetz. It's getting a bit old.
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?