achieve atomic operation because java volatile guarantees happens-before relation?
I have read about the happens-before for the volatile:
If Thread A writes to a volatile variable and Thread B subsequently reads the same volatilevariable, then all variables visible to Thread A before writing the volatile variable, will also be visible to Thread B after it has read the volatile variable.
Now, I have two varaibles:
static int m_x;
volatile static int m_y;
Now I have two threads, one only writes to them, and first write to m_x, and then write to m_y; The other one, only reads from them, first read m_y, and then, m_x.
My question is: is the write operation atomic? is the read operation atomic?
In my understanding, they should be atomic:
(1) On the side of writ thread, after (Write-1), it will not flush its cache to main-memory for m_x is NOT volatile, so, read-thread is not able to see the update; and after (Write-2), it will flush its cache to main-memory, for m_y is volatile;
(2) on the side of read thread, on (Read-1), it will update its cache from main memory, for m_y is volatile; and on (Read-2), it will NOT update its cache from main memory, for m_x is not volatile.
Because of the above two reason, I think the read thread should always observe the atomic value of the two variable. Right?
public class test {
static int m_x;
volatile static int m_y;
public static void main(String[] args) {
// write
new Thread() {
public
void run() {
while(true) {
int x = randInt(1, 1000000);
int y = -x;
m_x = x; // (Write-1)
m_y = y; // (Write-2)
}
}
}.start();
// read
new Thread() {
public
void run() {
while(true) {
int y = m_y; // (Read-1)
int x = m_x; // (Read-2)
int sum = y + x;
if (sum != 0) {
System.out.println("R:sum=" + sum);
System.out.println("R:x=" + x);
System.out.println("R:y=" + y);
System.out.println("\n");
}
}
}
}.start();
}
public static int randInt(int Min, int Max) {
return Min + (int)(Math.random() * ((Max - Min) + 1));
}
}
As stated in the comment, the two reads and writes are not atomic. You cannot achieve atomicity by using the volatile keyword.
This fact can be observed running your program.
To read/write both variables at the same time you either need proper synchronisation or create your own immutable value.
To do the later
public class ConcurrencyTestApp {
// use volatile for visibility
private volatile ImmutableValue immutableValue = new ImmutableValue(0, 0); // initial, non-null value
static class ImmutableValue {
private final int x;
private final int y;
ImmutableValue(final int x, final int y) {
this.x = x;
this.y = y;
}
int getX() {
return x;
}
int getY() {
return y;
}
#Override
public String toString() {
return String.format("x = %s\t| y = %s", x, y);
}
}
void replaceOldWithNewValue(final ImmutableValue newValue) {
immutableValue = newValue;
}
ImmutableValue getImmutableValue() {
return immutableValue;
}
static class Writer extends Thread {
private final ConcurrencyTestApp app;
Writer(ConcurrencyTestApp app) {
this.app = app;
}
volatile boolean isRunning = true;
#Override
public void run() {
while (isRunning) {
int x = randInt(1, 1000000);
int y = -x;
app.replaceOldWithNewValue(new ImmutableValue(x, y));
}
}
int randInt(int Min, int Max) {
return Min + (int) (Math.random() * ((Max - Min) + 1));
}
}
static class Reader extends Thread {
private final ConcurrencyTestApp app;
Reader(ConcurrencyTestApp app) {
this.app = app;
}
volatile boolean isRunning = true;
#Override
public void run() {
while (isRunning) {
ImmutableValue value = app.getImmutableValue();
System.out.println(value);
int x = value.getX();
int y = value.getY();
int sum = x + y;
if (sum != 0) {
System.out.println("R:sum=" + sum);
System.out.println("R:x=" + x);
System.out.println("R:y=" + y);
System.out.println("\n");
}
}
}
}
public static void main(String[] args) {
ConcurrencyTestApp app = new ConcurrencyTestApp();
Writer w = new Writer(app);
Reader r = new Reader(app);
w.start();
r.start();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
w.isRunning = false;
r.isRunning = false;
}
}
For further reference, I recommend the book Java concurrency in practice by Brian Goetz and Tim Peierls.
Addendum
...
Because of the above two reason, I think the read thread should always
observe the atomic value of the two variable. Right?
Wrong!
...and you are missing an important part.
For reference, see JSR 133 (Java Memory Model) FAQ by Jeremy Manson and Brian Goetz section What does volatile do?
In your program, there is nothing preventing the following:
Assume int m_x = x1 and int m_y = y1
Your Writer-Thread executes until Write-1
int m_x is now set to value x2 (which may or may not be visible to your Reader-Thread)
Your Writer-Thread's execution gets suspended (for whatever reason)
Your Reader-Thread executes Read-1 and Read-2 (there is nothing stopping the Reader-Thread from doing that)
int y = m_y which is still y1 because your Writer-Thread did not execute further yet
int x = m_x which may be x2 (but it also could still be x1)
Your Reader-Thread gets suspended and your Writer-Thread continues
int m_y is now set to value y2 (only now Read-1 would get y2 and Read-2 would be guaranteed to get x2 - unless your Writer-Thread continues)
... and so on
To see that yourself modify your writer
System.out.println("W0");
m_x = x; // non-volatile
System.out.println("W1: " + x);
m_y = y; // volatile
System.out.println("W2: " + y);
and reader thread code
System.out.println("R0");
int y = m_y; // volatile
System.out.println("R1: " + y);
int x = m_x; // non-volatile
System.out.println("R2: " + x);
So why does it not work for you?
From the reference
...volatile or not, anything that was visible to thread A when it writes to volatile field f becomes visible to thread B when it reads f.
Thus, your Reader thread is guaranteed to see the new values for m_x and m_y only when your Writer thread wrote the new value to m_y. But because no particular thread execution order is guaranteed the write operation Write-2 may not happen before Read-1 is executed.
Also see Java Volatile Keyword by Jakob Jenkov for a similar example to yours.
You assert that
"...after (Write-1), it will not flush its cache to main-memory for m_x is NOT volatile"
and
"... on (Read-2), it will NOT update its cache from main memory, for m_x is not volatile."
In fact, it is not possible to say whether or not the caches will be flushed (write), or whether or not values that are present in the cache (read). The JLS certainly does not make >>any<< guarantees for reads and writes to non-volatile variables. The guarantees apply to read and write operations on volatile variables ONLY.
While it is possible that you will observe consistent behavior for your program on certain platforms, that behavior is not guaranteed by the JLS.
Related
I do not understand why each time I run this code I get different answer ?
Correct answer should be one 98098 two 98099. Anyone have any ideas why this is not working that way ? For example one time answer comes back "one 49047 two 49047" then another time it comes back "one 40072 two 40072". I am so confused at this point and lack any reasonable explanation
public class TestThreads {
public static void main(String[] args){
ThreadOne t1 = new ThreadOne();
ThreadTwo t2 = new ThreadTwo();
Thread one = new Thread(t1);
Thread two = new Thread(t2);
one.start();
two.start();
}
}
class ThreadOne implements Runnable {
Accum a = Accum.getAccum();
public void run(){
for(int x = 0; x < 98; x++){
a.updateCounter(1000);
try{
Thread.sleep(50);
}catch(InterruptedException ex){
}
}
System.out.println("one " + a.getCount());
}
}
class ThreadTwo implements Runnable {
Accum a = Accum.getAccum();
public void run(){
for(int x = 0; x < 99; x++){
a.updateCounter(1);
try{
Thread.sleep(50);
}catch(InterruptedException ex){
}
}
System.out.println("two " + a.getCount());
}
}
class Accum {
private static Accum a = new Accum();
public static Accum getAccum(){
return a;
}
private int counter = 0;
public int getCount(){
return counter;
}
public void updateCounter(int add){
counter += add;
}
private Accum(){ }
}
As you have two threads updating the same data without thread safety, one thread easily overwrites the value set by the other one.
Each thread works on it's own thread cached value. e.g.
Thread 1 adds 1 one hundred times. It has the value 100
Thread 2 adds 1000 one hundred times. It has the value 100000
At this point, the one value is chosen. say it's thread 1's value.
Thread 1 adds 1 one hundred times. It has the value 200
Thread 2 adds 1000 one hundred times. It has the value 100100
This time, thread 2's value is chosen.
In the end only half the updates on average are retained as the value chosen is somewhat random.
You can get to 98099 by declaring the methods in Accum as synchronized.
This will ensure that only one of the threads can access it's information at a time.
As the other answers have pointed out, you are getting unexpected results because there is nothing to stop each thread overwriting what the other had done.
Try this:
class Accum {
private static Accum a = new Accum();
public static synchronized Accum getAccum(){
return a;
}
private int counter = 0;
public synchronized int getCount(){
return counter;
}
public synchronized void updateCounter(int add){
counter += add;
}
private Accum(){ }
}
your problem is this:
private static Accum a = new Accum();
public static Accum getAccum(){
return a;
}
Since its a STATIC there is only one instance shared by all threads. so when you set it in one thread, all threads get the same new value. if you remove the static notifier and instantiate a new object of class Accum for each thread it should work.
I am having trouble figuring out what my code is doing as this is my first time coding using multiple threads. To start off, in attempt to learn this type of programming I decided to write a miniature program that uses 8 threads to sum a number. However, no matter what I do it seems as if my program never stops when count = 10, it continues onward. I am using 8 threads as I planned on expanding my program to do large calculations. However, these threads are not correlating at all. They are going way past 10. I have used a synchronized method. I have tried a lock. I have tried implementing both at the same time. No matter what, it appears as if the threads still calculate past 10. See below for my current code.
public class calculator implements Runnable {
static int counter = 0;
static int sum = 0;
private synchronized static int getAndIncrement()
{
// System.out.println("counter is : " + counter);
int temp = counter;
counter = counter + 1;
System.out.println("counter is now : " + counter);
return temp;
}
private synchronized void addToSum(int value)
{
// System.out.println("sum : " + sum + " value: " + value);
sum += value;
}
#Override
public void run()
{
// TODO Auto-generated method stub
while(counter < 10)
{
int tempVal = getAndIncrement();
System.out.println("temp val : " + tempVal);
addToSum(tempVal);
// System.out.println("sum is now : " + sum);
}
}
}
This is my main method:
public static void main(String[] args)
{
calculator[] calc = new calculator[8];
Thread[] thread = new Thread[8];
final long startTime = System.currentTimeMillis();
for(int i = 0; i < 8; i++)
{
calc[i] = new calculator();
thread[i] = new Thread(calc[i]);
thread[i].start();
}
while(thread[0].isAlive() ||thread[1].isAlive() || thread[2].isAlive() || thread[3].isAlive() || thread[4].isAlive() || thread[5].isAlive() || thread[6].isAlive() || thread[7].isAlive())
{}
final long endTime = System.currentTimeMillis();
System.out.println(calculator.sum);
System.out.println("Execution time : " + (startTime - endTime));
}
I appreciate the help!
The synchronized keyword takes the object
lock. This means that two methods that are synchronized cannot execute on the same object. They will, however, execute concurrently on invocation on 2 different objects.
In your example, your code had 8 objects of calculator. The synchronized methods do not help you. Each thread uses it's separate object. You can completely remove the synchronized keyword, and your code will be semantically equivalent.
To avoid this, use the atomic version of the objects (AtomicInt) or lock on the objects themselves: synchronized(counter){...} but for this to work you will have to change the type to Integer.
I've just tested your sample and found the addToSum method doesn't work as expected here with heavy multi-thread, even if synchronized keyword is present.
Here, as sum variable is static, the method can be made static too.
After adding the static keyword, the behavior is as expected:
private static synchronized void addToSum(int value)
{
sum += value;
}
Here a simple test (addToSum replaced by incSum for simplicity) :
class IncrementorThread implements Runnable {
private static int sum = 0;
private static synchronized void incSum()
{
sum ++;
}
public void run() {
incSum();
Thread.yield();
}
}
void testIncrementorThread1() {
ExecutorService executorService = Executors.newCachedThreadPool();
//ExecutorService executorService = Executors.newSingleThreadExecutor() // result always ok without needing concurrency precaution
for(int i = 0; i < 5000; i++)
executorService.execute(new IncrementorThread());
executorService.shutdown();
executorService.awaitTermination(4000, TimeUnit.MILLISECONDS);
System.out.println("res = "+IncrementorThread.sum); // must be 5000
}
Result must be 5000, which is not the case if we remove the static keyword from the method incSum()
I have an object Rotor which has a goalSpeed and a currentSpeed. Each one tries to change its currentSpeed to match the goalSpeed set. I have 4 of these rotors running ing 4 separate threads. Each one gets assigned a new goalSpeed periodically by a controller.
When I attempt in each Rotor to change its currentSpeed, I cannot ever exceed the sum of all rotor's currentSpeed to exceed X value. sum(currentSpeed(Rotor1) + ... + currentSpeed(Rotor2)) !> X.
Here is my issue: when I check wether I can increase the current speed of a Rotor, I make an if statement on the sum of speeds condition. However, it is possible that right after this check, since each rotor is a separate thread that another one changes its value. Therefore my check in the other thread is not valid anymore. How can I make sure that while I'm in the setNewSpeed() method of one rotor, no other rotor will change its current speed?
class Rotor implements Runnable {
private int id;
private int goalSpeed;
private int currentSpeed;
private Controller controller;
private int Y;
private int failedAttempts;
private int successAttempts;
private int maxSpeed;
public int getSuccessAttempts() {
return successAttempts;
}
public void setSuccessAttempts(int successAttempts) {
this.successAttempts = successAttempts;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
public int getFailedAttempts() {
return failedAttempts;
}
public Rotor(Controller c, int Y, int id){
this.controller = c;
this.Y = Y;
this.id = id;
this.currentSpeed = 0;
this.failedAttempts = 0;
this.goalSpeed = 0;
this.maxSpeed = 0;
this.successAttempts = 0;
}
synchronized public void setGoalSpeed(int s){
this.goalSpeed = s;
}
public int getCurrentSpeed(){
return currentSpeed;
}
synchronized private void setNewSpeed(){
int currentDrain = 0;
for(Rotor r : controller.getRotors()){
currentDrain = currentDrain + r.getCurrentSpeed();
}
if((currentDrain + (goalSpeed - currentSpeed)) > 20){
//we cannot increase by total amount because drain too high
System.out.println("failed");
this.failedAttempts++;
currentSpeed = currentSpeed + (20 - currentDrain);
System.out.println("currentSpeed:" + currentSpeed);
} else {
System.out.println("success");
successAttempts++;
currentSpeed = goalSpeed;
}
// System.out.println("goalSpeed:" + goalSpeed);
// System.out.println("currentDrain:" + currentDrain);
}
public void run() {
try {
while(true){
setNewSpeed();
if(currentSpeed > maxSpeed){
maxSpeed = currentSpeed;
}
Thread.sleep(Y);
}
} catch (InterruptedException e) {
System.out.println("Rotor " + id + ": checks=" + (int)(successAttempts + failedAttempts) + ", success rate=" + successAttempts + ", failedAttempts=" + failedAttempts + ", max=" + maxSpeed);
}
}
}
Synchronize on a lock that's shared between all the rotors. Now each of them is synchronizing on their own lock (i.e. this), so even though the method is synchronized, it can be called on different objects at the same time.
The most simple way to synchronize them all is to use a static synchronized method.
That said, using an explicit lock object shared among the instances is probably a better approach.
1) You should not write
synchronized private void setNewSpeed() and synchronized public void setGoalSpeed(int s)
but private synchronized void setNewSpeed() and public synchronized void setGoalSpeed(int s) if you want to respect conventions and standard.
2) You declare two synchronized methods in your Rotor Runnable class but it makes no sense because in the synchronized methods you don't manipulate data shared between the threads.
3) You have multiple ways to address your problem.
A flexible solution consists of using a artificial object shared between the threads and performing the lock on this object when you call the setNewSpeed() method. It allows each tread to wait for the lock to be removed before entering in setNewSpeed().
Here is the idea to implement the solution :
Before instantiating the Rotor, create the shared object in this way :
Object lockObject = new Object();
change public Rotor(Controller c, int Y, int id) to public Rotor(Controller c, int Y, int id, Object lockObject)
invoke the constructor of Rotor by adding the same lockObject instance for all Rotors which you want synchronize between them the speed change.
Store the lockObject as an instance field of the Rotor in the constructor body.
In Rotor use the lockObject to make the synchronization in this way :
sample code :
private void setNewSpeed(){
synchronized(lockObject){
... your actual processing
}
}
I'm developing a circular buffer with two Threads: Consumer and Producer.
I'm using active waiting with Thread.yield.
I know that it is possible to do that with semaphores, but I wanted the buffer without semaphores.
Both have a shared variable: bufferCircular.
While the buffer is not full of useful information, producer write data in the position pof array, and while there are some useful information consumer read data in the position c of array. The variable nElem from BufferCircular is the number of value datas that haven't been read yet.
The program works quite good 9/10 times that runs. Then, sometimes, it get stucks in a infinite loop before show the last element on screen (number 500 of loop for), or just dont' show any element.
I think is probably a liveLock, but I can't find the mistake.
Shared Variable:
public class BufferCircular {
volatile int[] array;
volatile int p;
volatile int c;
volatile int nElem;
public BufferCircular(int[] array) {
this.array = array;
this.p = 0;
this.c = 0;
this.nElem = 0;
}
public void writeData (int data) {
this.array[p] = data;
this.p = (p + 1) % array.length;
this.nElem++;
}
public int readData() {
int data = array[c];
this.c = (c + 1) % array.length;
this.nElem--;
return data;
}
}
Producer Thread:
public class Producer extends Thread {
BufferCircular buffer;
int bufferTam;
int contData;
public Productor(BufferCircular buff) {
this.buffer = buff;
this.bufferTam = buffer.array.length;
this.contData = 0;
}
public void produceData() {
this.contData++;
this.buffer.writeData(contData);
}
public void run() {
for (int i = 0; i < 500; i++) {
while (this.buffer.nElem == this.bufferTam) {
Thread.yield();
}
this.produceData();
}
}
}
Consumer Thread:
public class Consumer extends Thread {
BufferCircular buffer;
int cont;
public Consumer(BufferCircular buff) {
this.buffer = buff;
this.cont = 0;
}
public void consumeData() {
int data = buffer.readData();
cont++;
System.out.println("data " + cont + ": " + data);
}
public void run() {
for (int i = 0; i < 500; i++) {
while (this.buffer.nElem == 0) {
Thread.yield();
}
this.consumeData();
}
}
}
Main:
public class Main {
public static void main(String[] args) {
Random ran = new Random();
int tamArray = ran.nextInt(21) + 1;
int[] array = new int[tamArray];
BufferCircular buffer = new BufferCircular(array);
Producer producer = new Producer (buffer);
Consumer consumer = new Consumer (buffer);
producer.start();
consumer.start();
try {
producer.join();
consumer.join();
} catch (InterruptedException e) {
System.err.println("Error with Threads");
e.printStackTrace();
}
}
}
Any help will be welcome.
Your problem here is that your BufferCircular methods are sensitive to race conditions. Take for example writeData(). It executes in 3 steps, some of which are also not atomic:
this.array[p] = data; // 1
this.p = (p + 1) % array.length; // 2 not atomic
this.nElem++; // 3 not atomic
Suppose that 2 threads entered writeData() at the same time. At step 1, they both have the same p value, and both rewrite array[p] value. Now, array[p] is rewritten twice and data that first thread had to write, is lost, because second thread wrote to the same index after. Then they execute step 2--and result is unpredictable since p can be incremented by 1 or 2 (p = (p + 1) % array.length consists of 3 operations, where threads can interact). Then, step 3. ++ operator is also not atomic: it uses 2 operations behind the scenes. So nElem becomes also incremented by 1 or 2.
So we have fully unpredictable result. Which leads to poor execution of your program.
The simplest solution is to make readData() and writeData() methods serialized. For this, declare them synchronized:
public synchronized void writeData (int data) { //...
public synchronized void readData () { //...
If you have only one producer and one consumer threads, race conditions may occur on operations involving nElem. Solution is to use AtomicInteger instead of int:
final AtomicInteger nElem = new AtomicInteger();
and use its incrementAndGet() and decrementAndGet() methods.
Consider the following code picked from Joshua Bloch - Effective Java, page 263
// Broken - requires synchronization!
private static volatile int nextSerialNumber = 0;
public static int generateSerialNumber() {
return nextSerialNumber++;
}
One way to fix the
generateSerialNumber method is to add
the synchronized modifier to its
declaration. This ensures that
multiple invocations won’t be
interleaved, and that each invocation
will see the effects of all previous
invocations. Once you’ve done that,
you can and should remove the volatile
modifier from nextSerialNumber. To
bulletproof the method, use long
instead of int, or throw an exception
if nextSerialNumber is about to wrap.
I understand that we can remove volatile after we make generateSerialNumber synchronized, as it is redundant. But, does it make any harm? Any performance penalty if I am having both synchronized and volatile like
private static volatile int nextSerialNumber = 0;
public static synchronized int generateSerialNumber() {
return nextSerialNumber++;
}
What does, use long instead of int means? I do not understand how this bulletproof the method?
It simply means that long will hold many more numbers than int.
or throw an exception if nextSerialNumber is about to wrap
implies that the concern here is that you run out of numbers and you end up with an overflow. You want to ensure that does not happen. The thing is, if you are at the maximum integer possible and you increment, the program does not fail. It happily goes not incrementing but the result is no longer correct.
Using long will postpone this possibility. Throwing the exception will indicate that it has happened.
What does, use long instead of int means?
It ensures that serial numbers don't roll over for a long, long time to come. Using an int you might use up all the available values (thus nextSerialNumber will have the maximum possible int value), then at the next increment the value is silently rolled over to the smallest (negative) int value, which is almost certainly not what you would expect from serial numbers :-)
IMHO volatile/AtomicInteger is faster than synchronized in a multi-threaded context. In a single threaded micro-benchmark they are much the same. Part of the reson for this is that synchronized is a OS call whereas volatile is entirely user space.
I get this output from the following program on Java 6 update 23.
Average time to synchronized++ 10000000 times. was 110368 us
Average time to synchronized on the class ++ 10000000 times. was 37140 us
Average time to volatile++ 10000000 times. was 19660 us
I cannot explain why synchronizing on the class is faster than a plain object.
Code:
static final Object o = new Object();
static int num = 0;
static final AtomicInteger num2 = new AtomicInteger();
public static void main(String... args) throws InterruptedException {
final int runs = 10 * 1000 * 1000;
perfTest(new Runnable() {
public void run() {
for (int i = 0; i < runs; i++)
synchronized (o) {
num++;
}
}
public String toString() {
return "synchronized++ " + runs + " times.";
}
}, 4);
perfTest(new Runnable() {
public void run() {
for (int i = 0; i < runs; i++)
synchronized (Main.class) {
num++;
}
}
public String toString() {
return "synchronized on the class ++ " + runs + " times.";
}
}, 4);
perfTest(new Runnable() {
public void run() {
for (int i = 0; i < runs; i++)
num2.incrementAndGet();
}
public String toString() {
return "volatile++ " + runs + " times.";
}
}, 4);
}
public static void perfTest(Runnable r, int times) throws InterruptedException {
ExecutorService es = Executors.newFixedThreadPool(times);
long start = System.nanoTime();
for (int i = 0; i < times; i++)
es.submit(r);
es.shutdown();
es.awaitTermination(1, TimeUnit.MINUTES);
long time = System.nanoTime() - start;
System.out.println("Average time to " + r + " was " + time / times / 10000 + " us");
}
One way of bulletproofing would be (in addition to the above)
if (nextSerialNumber >= Integer.MAX_VALUE)
// throw an Exception;
or print out something, or catch that exception in calling routine