According to this specification, two java threads can not coordinate through non-volatile fields. Why is my code running okay?
public class TestVolatileExample {
static int pairCount = 1000;
static VolatileExample[] exps = new VolatileExample[pairCount];
static{
for(int i = 0;i<pairCount;i++){
exps[i] = new VolatileExample();
}
}
#Test
public void test() throws InterruptedException{
final int valuePair[][] = new int[pairCount][2];
Thread[] threads = new Thread[pairCount*2];
for(int i = 0;i<pairCount;i++){
final int index = i;
//final VolatileExample exp = new VolatileExample();
//writer
Thread writer = new Thread(new Runnable(){
#Override
public void run() {
VolatileExample exp = exps[index];
int val = new Random().nextInt(100);
valuePair[index][0] = val;
exp.set(val);
}
});
writer.start();
threads[i*2] = writer;
//reader
Thread reader = new Thread(new Runnable(){
#Override
public void run() {
VolatileExample exp = exps[index];
while(!exp.changed()){
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//System.out.println("waitting for change...");
}
int val = exp.get();
valuePair[index][1] = val;
}
});
reader.start();
threads[i*2+1] = reader;
}
for(Thread t : threads){
t.join();
}
for(int i = 0;i<pairCount;i++){
int write = valuePair[i][0];
int read = valuePair[i][1];
System.out.println(write+"," + read);
Assert.assertEquals(write,read);
}
}
}
public class VolatileExample {
private int x;
private boolean changed = false;
public void set(int x){
this.x = x;
this.changed = true;
System.out.println("changed...");
}
public int get(){
return x;
}
public boolean changed(){
return changed;
}
}
You see, the reader thread is waiting for the value x in VolatileExample until the flag property been changed. According to Java specification, the non-volatile property,'changed', will be saved in the respective cache of each thread. But why did my program get the expected results?
I started 1000 pairs of reading and write threads, and each read thread did read the values written by the write threads.
Is there anything wrong with me?
The page you linked to says:
The compiler is free to read the field this.done just once, and reuse
the cached value in each execution of the loop. This would mean that
the loop would never terminate, even if another thread changed the
value of this.done.
This means whether your code works or not depends on whether the compiler decides to cache your variables (doesn't work) or not (works). It is free to do so if it wants, but it doesn't have to.
So your code may or may not work depending on things that are not under your control.
Related
I tried out multithreading for a project I'm making. in the project I need to do a certain calculation multiple times every time I call for a certain function. I tried making some testing code to understand how to do it, but I can't get it to work properly (the code seems to work perfectly when I debug it, but if I run it normally it doesn't work past the first cycle).
in the code there is an endless loop that mimics my project's calling for a function multiple times. I tried to do it so the thread runs while changeflag is true, and change the flag to false after every run of the calculation so it would stop from calculating it again and again, and after "calling" the function I change it to true back, so it would be able to calculate again.
following is my code:
import java.util.ArrayList;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
public class Main {
public static void main(String[] args) throws InterruptedException {
BlockingQueue<Result> queue = new SynchronousQueue<>();
int loops = 0;
MyThread[] arr = new MyThread[10];
ArrayList<Result> ress = new ArrayList<>();
for (int i = 0; i < arr.length; i++) {
arr[i] = new MyThread(i, queue);
arr[i].start();
}
while (true) {
System.out.println(loops++);
while (ress.size() < arr.length){
ress.add(queue.take());
}
while (!ress.isEmpty()){
arr[ress.get(0).getSign()].setChangeflag(true);
ress.remove(0);
}
}
}
}
import java.util.Random;
import java.util.concurrent.BlockingQueue;
public class MyThread extends Thread{
private boolean changeflag = true;
private boolean runflag = true;
private int sign;
private BlockingQueue<Result> queue;
Random rnd = new Random();
public MyThread(int sign, BlockingQueue<Result> queue){
this.sign = sign;
this.queue = queue;
}
public void run(){
while (runflag){
if(changeflag){
changeflag = false;
try {
queue.put(sense());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public Result sense(){
return new Result( rnd.nextInt(10), sign);
}
public synchronized void setChangeflag(boolean changeflag) {
this.changeflag = changeflag;
}
}
public class Result {
private double res;
private int sign;
public Result(double res, int sign) {
this.res = res;
this.sign = sign;
}
public int getSign() {
return sign;
}
}
I recommend using Executors.newCachedThreadPool(). This will return an ExecutorService which you can use to queue your calculations using submit(Callable), which returns a Future on which you can block as desired. If you queue many tasks you can just keep a list of Futures as needed or a list of tasks then submit them to the ExecutorService.
Also note it's usually not recommended to extend from Thread.
Hope this helps!
The only reason I, at least, can see why you need Threads here is to do other work while waiting for the sense method to complete in the background. For example render some graphics or interact with the user.
If your main Thread is required to wait until all the sense job is complete for each request, then you don't need Threads. Just call the method sense directly in the main Thread.
On the other hand, if you need a background Thread doing the sense job while the main Thread is doing other work, then you will need two Threads: one is the main, and the other is the background-job. Then you probably need to have a producer-consumer pattern, where the producer (the main Thread) creates the requests and the consumer (the background Thread) executes the sense method. But then it seems like the roles are turned around again like you want to wait in the main Thread all the requests to complete after you submit them. If that is the case then you can start all the MyThreads and then call join on them when you are ready to wait for their results. For example:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
public class Main {
public static class Result {
private final int index;
private final Object value;
public Result(final int index,
final Object value) {
this.index = index;
this.value = value;
}
public int getIndex() {
return index;
}
public Object getValue() {
return value;
}
}
public static class MyRunnable implements Runnable {
private final int index;
private final Collection<Result> sharedResults;
public MyRunnable(final int index,
final Collection<Result> sharedResults) {
this.index = index;
this.sharedResults = Objects.requireNonNull(sharedResults);
}
#Override
public void run() {
final Result res = sense(); //Calculating outside the synchronized block.
synchronized (sharedResults) { //Synchronizing, because the actual instance of this collection might not be synchronized.
sharedResults.add(res);
}
}
private Result sense() {
return new Result(index, "Value" + index);
}
}
public static void main(final String[] args) {
final Thread[] t = new Thread[10];
final Collection<Result> sharedResults = new ArrayList<>();
for (int i = 0; i < t.length; ++i) {
t[i] = new Thread(new MyRunnable(i, sharedResults));
t[i].start();
}
for (final Thread thread: t)
try { thread.join(); } catch (final InterruptedException ix) { ix.printStackTrace(); }
sharedResults.forEach(res -> System.out.println("Result " + res.getIndex() + " with value \"" + res.getValue() + "\"."));
}
}
Another way is to use an ExecutorService like suggested by #m0skit0 and utilize the returned Future objects to wait for the results.
I have to create a hedge simulator. There is eg. 10 segments of it and each of them should have its own dedicated Thread simulating grow of the segment (each time we're about to calculate whether segment growed up, we should perform random test).
In addition there should be one additional, gardener Thread.
Gardener should cut segment of hence, when its size reaches 10 (then he cuts its size back to initial level of 1 and adds notifies it in his notes).
My attempt to make it working was like this:
public class Segment implements Runnable {
private int currentSize;
#Override
public void run() {
if(Math.random() < 0.3)
incrementSize();
}
private synchronized void incrementSize() {
currentSize++;
}
public synchronized int getCurrentSize() {
return currentSize;
}
public synchronized void setCurrentSize(int newSize) {
currentSize = newSize;
}
}
public class Gardener implements Runnable {
private int[] segmentsCutAmount = new int[10]; //Gardener notes
private Collection<Segment> segments;
public Gardener(Collection<Segment> segmentsToLookAfter) {
segments = segmentsToLookAfter;
}
#Override
public void run() {
while(true) {
//Have no idea how to deal with 10 different segments here
}
}
}
public class Main {
private Collection<Segment> segments = new ArrayList<>():
public void main(String[] args) {
Main program = new Main();
for(int i = 0; i < 10; i++)
program.addSegment();
Thread gardenerThread = new Thread(new Gardener(program.segments));
}
private void addSegment(Collection<Segment> segments) {
Segment segment = new Segment();
Thread segmentThread = new Thread(segment);
segmentThread.start();
segments.add(segment);
}
}
I am not sure what am I supposed to do, when segment reaches max height.
If there was 10 gardeners, every of them could observe one segment, but, unfortunelly, gardener is a lonely shooter - he has no family and his friends are very busy and are not willing to help him. And are you willing to help me? :D
I generally know basics of synchronization - synchronized methods/blocks, Locks, wait and notify methods, but this time I have totally no idea what to do :(
Its like horrible deadlock! Of course I am not expecting to be spoonfeeded. Any kind of hint would be very helpful as well. Thank you in advance and have a wonderful day!
About that queue. You can use the ExecutorService for that.
Letting the Hedge grow
So let's you have a hedge that can grow and be cut.
class Hedge {
private AtomicInteger height = new AtomicInteger(1);
public int grow() {
return height.incrementAndGet();
}
public int cut() {
return height.decrementAndGet();
}
}
And then you have an environment that will let the hedge grow. This will simulate the hedge sections; each environment is responsible for one of the sections only. It will also notify a Consumer<Integer> when the hedge size has gone.
class SectionGrower implements Runnable {
public static final Random RANDOM = new Random();
private final Hedge hedge;
private final Consumer<Integer> hedgeSizeListener;
public SectionGrower (Hedge h, Consumer<Integer> hl) {
hedge = h;
hedgeSizeListener = hl
}
public void run() {
while (true) { // grow forever
try {
// growing the hedge takes up to 20 seconds
Thread.sleep(RANDOM.nextInt(20)*1000);
int sectionHeight = hedge.grow();
hedgeSizeListener.accept(sectionHeight);
} catch (Exception e) {} // do something here
}
}
}
So at this point, you can do this.
ExecutorService growingExecutor = Executors.newFixedThreadPool(10);
Consumer<Integer> printer = i -> System.out.printf("hedge section has grown to %d\n", i.intValue());
for (int i = 0; i < 10; i++) {
Hedge section = new Hedge();
Environment grower = new SectionGrower(section, printer);
growingExecutor.submit(grower::run);
}
This will grow 10 hedge sections and print the current height for each as they grow.
Adding the Gardener
So now you need a Gardener that can cut the hedge.
class Gardener {
public static final Random RANDOM = new Random();
public void cutHedge(Hedge h) {
try {
// cutting the hedge takes up to 10 seconds
Thread.sleep(RANDOM.nextInt(10)*1000);
h.cut();
} catch (Exception e) {} // do something here
}
}
Now you need some construct to give him work; this is where the BlockingQueue comes in. We've already made sure the Environment can notify a Consumer<Integer> after a section has grown, so that's what we can use.
ExecutorService growingExecutor = Executors.newFixedThreadPool(10);
// so this is the queue
ExecutorService gardenerExecutor = Executors.newSingleThreadPool();
Gardener gardener = new Gardener();
for (int i = 0; i < 10; i++) {
Hedge section = new Hedge();
Consumer<Integer> cutSectionIfNeeded = i -> {
if (i > 8) { // size exceeded?
// have the gardener cut the section, ie adding item to queue
gardenerExecutor.submit(() -> gardener.cutHedge(section));
}
};
SectionGrower grower = new SectionGrower(section, cutSectionIfNeeded);
growingExecutor.submit(grower::run);
}
So I haven't actually tried this but it should work with some minor adjustments.
Note that I use the AtomicInteger in the hedge because it might grow and get cut "at the same time", because that happens in different threads.
The in following code Gardner waits for Segment to get to an arbitrary value of 9.
When Segment gets to 9, it notifies Gardner, and waits for Gardner to finish trimming:
import java.util.ArrayList;
import java.util.Collection;
public class Gardening {
public static void main(String[] args) {
Collection<Segment> segments = new ArrayList<>();
for(int i = 0; i < 2; i++) {
addSegment(segments);
}
Thread gardenerThread = new Thread(new Gardener(segments));
gardenerThread.start();
}
private static void addSegment(Collection<Segment> segments) {
Segment segment = new Segment();
Thread segmentThread = new Thread(segment);
segmentThread.start();
segments.add(segment);
}
}
class Gardener implements Runnable {
private Collection<Segment> segments;
private boolean isStop = false; //add stop flag
public Gardener(Collection<Segment> segmentsToLookAfter) {
segments = segmentsToLookAfter;
}
#Override
public void run() {
for (Segment segment : segments) {
follow(segment);
}
}
private void follow(Segment segment) {
new Thread(() -> {
Thread t = new Thread(segment);
t.start();
synchronized (segment) {
while(! isStop) {
try {
segment.wait(); //wait for segment
} catch (InterruptedException ex) { ex.printStackTrace();}
System.out.println("Trimming Segment " + segment.getId()+" size: "
+ segment.getCurrentSize() ); //add size to notes
segment.setCurrentSize(0); //trim size
segment.notify(); //notify so segment continues
}
}
}).start();
}
}
class Segment implements Runnable {
private int currentSize;
private boolean isStop = false; //add stop flag
private static int segmentIdCounter = 0;
private int segmentId = segmentIdCounter++; //add an id to identify thread
#Override
public void run() {
synchronized (this) {
while ( ! isStop ) {
if(Math.random() < 0.0000001) {
incrementSize();
}
if(getCurrentSize() >= 9) {
notify(); //notify so trimming starts
try {
wait(); //wait for gardener to finish
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
}
private synchronized void incrementSize() {
currentSize++;
System.out.println("Segment " + getId()+" size: "
+ getCurrentSize() );
}
public synchronized int getCurrentSize() { return currentSize; }
public synchronized void setCurrentSize(int newSize) {
currentSize = newSize;
}
public int getId() { return segmentId; }
}
The mutual waiting mechanizem can be implemented also with CountDownLatch.
Note that my experience with threads is limited. I hope other users comment and suggest improvements.
I have two threads. The first changes the value of variable Data. And second one print the value if its value has changed. I am trying to do that second thread just print each time that the variable's value changed, but I don't reach success. Someone can help me?
thread 1
class someservice{
volatile int data;
Boolean Flag = false;
public void mymethod(){
flag = true;
for (Integer i = 1; i < sheet.getRows(); i++) {
data = someMethod(); //this method when called return a new
//value
}
flag = false;
...
}
}
thread 2
Promise p = task {
try {
while (true) {
if (engineService.getFlag()) {
print(someservice.data);
}else{
break;
}
}
} catch(Throwable t) {
...
}
}
Since you mention Promises, I infer you are familiar with future/ promise in +C++11
in java there is a similar approach, with future callable...
public class HW5 {
public static void main(String[] argv) throws InterruptedException, ExecutionException {
FutureTask<Boolean> myFutureTask = new FutureTask<>(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
// implement the logic here and return true if everything was
// ok, false otherwise.
Thread.sleep(5000);
System.out.println("dddd");
return System.currentTimeMillis() % 2 == 0;
}
});
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.execute(myFutureTask);
Boolean result = myFutureTask.get();
System.out.println("Done!");
}
}
FutureTask in a class that takes a callable which can return an Object after its job is done... in Order to execute the Future task you can use a Executor service, especifically calling the method execute, since you need to wait for the thread to do the job then is necessary that you call Future.get, that will basically blocks the main thread until the future is done, to verify the result, just read the variable result..
You could use the notify() and notifyAll() methods within thread. Check out this link: https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
public synchronized void guardedJoy() {
// This guard only loops once for each special event, which may not
// be the event we're waiting for.
while(!joy) {
try {
wait();
} catch (InterruptedException e) {}
}
System.out.println("Joy and efficiency have been achieved!");
}
public synchronized notifyJoy() {
joy = true;
notifyAll();
}
You have to look up more data about Concurrent programming,I can tell you now some basics,well,not so so basic,but i will do my best:
Here,you have a Monitor,it is an abstract concept,in resume,a Monitor is a
class with all it's
method using"syncronized"
as modifier, it means,
that only
one thread
can access
the method
at once.So,
in the
monitor is
the variable
that you
want to print,
and the"flag",
that tells you if
the variable
was modified.Finally,
you can
see the
most important thing,the"wait()"and"notify()"methods,
those method
stops the thread,or"play"
them again.
You ask
here in
the printValue() method, if your variable was changed, if the variable was'nt change, put the thead to sleep with the wait() method, and when the other
method changeValue() is executed, the value is modified, and the notify() method is called, waking up the thread, so, doing all this, you can guarantee three things:
Safety: meaning that the threads will do that you want
Absence of deadlock: meaning that the thread that is put to sleep, will be awake in the future.
Mutex: meaning that only one thread is executing the critical code, for example, the op. "++" is not atomic, is Subdivided inside in more the one action, create a local var, read the var, sum, and asign, so, if more than one thread are in the game, the value may not be consecutive, example:
i = 0;
i ++;
output: 1;
output: 2;
output: 3;
output: 5;
output: 4;
output: 7;
That could happen, and even so, that will happen in the next code, because there a more than one thread executing. Well, this is the way to program with several threads, more or less
public class Monitor {
private int value = 0;
public static boolean valueHasChanged = false;
public synchronized int changeValue(int newValue){
this.value = newValue;
Monitor.valueHasChanged = true;
this.notify();
return this.value + 1;
}
public synchronized void printValue(){
while(!Monitor.valueHasChanged){
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(this.value);
Monitor.valueHasChanged = false;
}
public static void main(String[] args) {
Monitor ac = new Monitor();
BClass t1 = new BClass(ac);
AClass t2 = new AClass(ac);
t1.start();
t2.start();
}
public int getValue() {
return this.value;
}
}
Now the threads:
public class AClass extends Thread{
private Monitor ac;
public AClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
while(true){
this.ac.printValue();
}
}
}
And finally:
public class BClass extends Thread{
private Monitor ac;
public BClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
int v = 0;
while(true){
this.ac.changeValue(v);
v++; // this sum is not secure, if you want to print an
// ascending order, the code is diferent, I will show in
// above.
}
}
Now, if you want an ordered print:
the monitor will look like:
public class Monitor {
private int value = 0;
public boolean valueHasChanged = false;
private boolean hasPrint = true;
public synchronized void changeValue(int newValue) {
this.value = newValue;
this.valueHasChanged = true;
this.notify();
}
public synchronized void changeValuePlusOne() {
while (!hasPrint) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.value++;
this.valueHasChanged = true;
this.hasPrint = false;
this.notifyAll();
}
public synchronized void printValue() {
while (!this.valueHasChanged) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(this.value);
this.valueHasChanged = false;
this.hasPrint = true;
this.notifyAll();
}
public static void main(String[] args) {
Monitor ac = new Monitor();
BClass t1 = new BClass(ac);
AClass t2 = new AClass(ac);
t1.start();
t2.start();
}
public int getValue() {
return this.value;
}
}
And the Threads:
public class BClass extends Thread{
private Monitor ac;
public BClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
while(true){
this.ac.changeValuePlusOne();
}
}
}
The other Thread look equals:
public class AClass extends Thread{
private Monitor ac;
public AClass(Monitor ac) {
this.ac = ac;
}
#Override
public void run() {
while(true){
this.ac.printValue();
}
}
}
I have a Metrics class that's supposed to keep track of how many transactions we process each second and how long they take. The relevant part of its structure looks like this:
public class Metrics {
AtomicLong sent = new AtomicLong();
AtomicLong totalElapsedMsgTime = new AtomicLong();
AtomicLong sentLastSecond = new AtomicLong();
AtomicLong avgTimeLastSecond = new AtomicLong();
public void outTick(long elapsedMsgTime){
sent.getAndIncrement();
totalElapsedMsgTime.getAndAdd(elapsedMsgTime);
}
class CalcMetrics extends TimerTask {
#Override
public void run() {
sentLastSecond.set(sent.getAndSet(0));
long tmpElapsed = totalElapsedMsgTime.getAndSet(0);
long tmpSent = sentLastSecond.longValue();
if(tmpSent != 0) {
avgTimeLastSecond.set(tmpElapsed / tmpSent);
} else {
avgTimeLastSecond.set(0);
}
}
}
}
My issue is that the outTick function will get called hundreds of times a second from lots of different threads. Being AtomicLong already ensures that each variable is individually thread safe, and they don't interact with each other in that function, so I don't want a lock that will make one call to outTick block another thread's call to outTick. It's perfectly fine if a couple of different threads increment the sent variable and then they both add to the totalElapsedMsgTime variable.
However, once it gets into CalcMetrics run method (which only happens once each second), they do interact. I want to ensure that I can pick up and reset both of those variables without being in the middle of an outTick call or having another outTick call occur between picking up one variable and the next.
Is there any way of doing this? (Does my explanation even make sense?) Is there a way of saying that A cannot interleave with B but multiple B's can interleave with each other?
EDIT:
I went with the ReadWriteLock that James suggested. Here's what my result looks like for anyone interested:
public class Metrics {
AtomicLong numSent = new AtomicLong();
AtomicLong totalElapsedMsgTime = new AtomicLong();
long sentLastSecond = 0;
long avgTimeLastSecond = 0;
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private final Lock readLock = readWriteLock.readLock();
private final Lock writeLock = readWriteLock.writeLock();
public void outTick(long elapsedMsgTime) {
readLock.lock();
try {
numSent.getAndIncrement();
totalElapsedMsgTime.getAndAdd(elapsedMsgTime);
}
finally
{
readLock.unlock();
}
}
class CalcMetrics extends TimerTask {
#Override
public void run() {
long elapsed;
writeLock.lock();
try {
sentLastSecond = numSent.getAndSet(0);
elapsed = totalElapsedMsgTime.getAndSet(0);
}
finally {
writeLock.unlock();
}
if(sentLastSecond != 0) {
avgTimeLastSecond = (elapsed / sentLastSecond);
} else {
avgTimeLastSecond = 0;
}
}
}
}
The usual solution is to wrap all variables as one atomic data type.
class Data
{
long v1, v2;
Data add(Data another){ ... }
}
AtomicReference<Data> aData = ...;
public void outTick(long elapsedMsgTime)
{
Data delta = new Data(1, elapsedMsgTime);
aData.accumulateAndGet( delta, Data:add );
}
In your case, it may not be much faster than just locking.
There is another interesting lock in java8 - StampedLock . The javadoc example pretty much matches your use case. Basically, you can do optimistic reads on multiple variables; afterwards, check to make sure that no writes were done during the reads. In your case, "hundreds" of writes per second, the optimistic reads mostly would succeed.
Sounds like you need a reader/writer lock. (java.util.concurrent.locks.ReentrantReadWriteLock).
Your outTick() function would lock the ReaderLock. Any number of threads are allowed to lock the ReaderLock at the same time.
Your calcMetrics() would lock the WriterLock. No new readers are allowed in once a thread is waiting for the writer lock, and the writer is not allowed in until all the readers are out.
You would still need the atomics to protect the individual counters that are incremented by outTick().
Use locks ( https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html ). Once you implement locks you'll have finer control. An additional side effect will be that you won't need to use AtomicLong anymore (although you still can); you can use volatile long instead, which would be more efficient. I did not make that change in the example.
Basically just create a new Object:
private Object lock = new Object();
Then, use the synchronized keyword with that object around all the code that should never happen at the same time as another synchronized block with the same lock. Example:
synchronized(lock)
{
sent.getAndIncrement();
totalElapsedMsgTime.getAndAdd(elapsedMsgTime);
}
So your whole program will look like this (note: untested code)
public class Metrics {
private Object lock = new Object();
AtomicLong sent = new AtomicLong();
AtomicLong totalElapsedMsgTime = new AtomicLong();
AtomicLong sentLastSecond = new AtomicLong();
AtomicLong avgTimeLastSecond = new AtomicLong();
public void outTick(long elapsedMsgTime){
synchronized (lock)
{
sent.getAndIncrement();
totalElapsedMsgTime.getAndAdd(elapsedMsgTime);
}
}
class CalcMetrics extends TimerTask {
#Override
public void run() {
synchronized (lock)
{
sentLastSecond.set(sent.getAndSet(0));
long tmpElapsed = totalElapsedMsgTime.getAndSet(0);
long tmpSent = sentLastSecond.longValue();
if(tmpSent != 0) {
avgTimeLastSecond.set(tmpElapsed / tmpSent);
} else {
avgTimeLastSecond.set(0);
}
}
}
}
}
Edit: I threw together a quick (and ugly) efficiency test program and found that when I synchronize with locks, I get overall better performance. Note that the results of the first 2 runs are discarded because the timing results when the Java JIT still hasn't compiled all code paths to machine code are not representative of the long term runtime.
Results:
With Locks: 8365ms
AtomicLong: 21254ms
Code:
import java.util.concurrent.atomic.AtomicLong;
public class Main
{
private AtomicLong testA_1 = new AtomicLong();
private AtomicLong testB_1 = new AtomicLong();
private volatile long testA_2 = 0;
private volatile long testB_2 = 0;
private Object lock = new Object();
private volatile boolean a = false;
private volatile boolean b = false;
private volatile boolean c = false;
private static boolean useLocks = false;
public static void main(String args[])
{
System.out.println("Locks:");
useLocks = true;
test();
System.out.println("No Locks:");
useLocks = false;
test();
System.out.println("Locks:");
useLocks = true;
test();
System.out.println("No Locks:");
useLocks = false;
test();
}
private static void test()
{
final Main main = new Main();
new Thread()
{
public void run()
{
for (int i = 0; i < 80000000; ++i)
main.outTick(10);
main.a = true;
}
}.start();
new Thread()
{
public void run()
{
for (int i = 0; i < 80000000; ++i)
main.outTick(10);
main.b = true;
}
}.start();
new Thread()
{
public void run()
{
for (int i = 0; i < 80000000; ++i)
main.outTick(10);
main.c = true;
}
}.start();
long startTime = System.currentTimeMillis();
// Okay this isn't the best way to do this, but it's good enough
while (!main.a || !main.b || !main.c)
{
try
{
Thread.sleep(1);
} catch (InterruptedException e)
{
}
}
System.out.println("Elapsed time: " + (System.currentTimeMillis() - startTime) + "ms");
System.out.println("Test A: " + main.testA_1 + " " + main.testA_2);
System.out.println("Test B: " + main.testB_1 + " " + main.testB_2);
System.out.println();
}
public void outTick(long elapsedMsgTime)
{
if (!useLocks)
{
testA_1.getAndIncrement();
testB_1.getAndAdd(elapsedMsgTime);
}
else
{
synchronized (lock)
{
++testA_2;
testB_2 += elapsedMsgTime;
}
}
}
}
I am trying to write Thread Interference Example.
Below is my code:
class Counter {
private int c = 0;
public void increment() {
c++;
}
public void decrement() {
c--;
}
public int value() {
return c;
}
}
Suppose Thread A invokes increment at about the same time Thread B invokes decrement.
How to implement this one.
There is not guarantee how they will run it depends on OS scheduler. There is nothing better than this
Thread a = new ThreadA();
Thread b = new ThreadB();
a.start();
b.start();
To get two threads to start executing at the same time you can use a latch. (Which is to say, two threads that become available for execution as close together as possible.) Still for a single increment/decrement each it will probably take many runs to observe an interference. For a repeatable experiment you probably want to call increment/decrement several times in parallel and observe the final value of c.
final Counter counter = new Counter()
final CountDownLatch latch = new CountDownLatch(1);
Thread thread1 = new Thread(new Runnable() {
public void run() {
latch.await();
for (int i = 0; i < 100; i++) {
counter.increment();
}
}}).start():
Thread thread2 = new Thread(new Runnable() {
public void run() {
latch.await();
for (int i = 0; i < 100; i++) {
counter.decrement();
}
}}).start():
Thread.sleep(10);//give thread 2 a timeslice to hit the await
latch.countDown();
System.out.println(counter.value()); //non-zero value indicates interference
Now in this example if you try to execute and the output false shows interference.
How it works:
Both the Runnables keep a thread local count which is incremented for each invocation of increment() and decrement(). So after execution for some amount of time if we try to validate the values
Then you can say that:
value of Counter = invocation of increment() - invocation of decrement().
But when you try to verify this at the end of execution you get false. Which shows that the actual counter value was not as expected.
public static void main(String[] args) throws InterruptedException
{
Counter c = new Counter();
IncrementingRunnable incRunnable = new IncrementingRunnable(c);
DecrementingRunnable decRunnable = new DecrementingRunnable(c);
Thread tA = new Thread(incRunnable);
Thread tB = new Thread(decRunnable);
tA.start();tB.start();
Thread.sleep(10000);
stop = true;
tA.join();
tB.join();
//verify value
int actualCount = c.c;
int expectedCount = incRunnable.count - decRunnable.count;
System.out.println(actualCount == expectedCount);
}
public static volatile boolean stop = false;
static class IncrementingRunnable implements Runnable{
volatile int count = 0;
private Counter counter;
public IncrementingRunnable(Counter c) {
this.counter = c;
}
#Override
public void run() {
while(!stop){
counter.increment();
count++;
}
}
}
static class DecrementingRunnable implements Runnable{
volatile int count = 0;
private Counter counter;
public DecrementingRunnable(Counter c) {
this.counter = c;
}
#Override
public void run() {
while(!stop){
counter.decrement();
count++;
}
}
}
Now try changing the primitive c in Counter to AtomicInteger and see the output again. You will find that now the output is true.