I came across answers, here on SO, about Java flushing the work copy of variables within a synchronized block during exit. Similarly it syncs all the variable from main memory once during the entry into the synchronized section.
However, I have some fundamental questions around this:
What if I access mostly non-volatile instance variables inside my synchronized section? Will the JVM automatically cache those variables into the CPU registers at the time of entering into the block and then carry all the necessary computations before finally flushing them back?
I have a synchronized block as below: The underscored variables
_e.g._callStartsInLastSecondTrackerare all instance variables which I heavily access in this critical section.
public CallCompletion startCall()
{
long currentTime;
Pending pending;
synchronized (_lock)
{
currentTime = _clock.currentTimeMillis();
_tracker.getStatsWithCurrentTime(currentTime);
_callStartCountTotal++;
_tracker._callStartCount++;
if (_callStartsInLastSecondTracker != null)
_callStartsInLastSecondTracker.addCall();
_concurrency++;
if (_concurrency > _tracker._concurrentMax)
{
_tracker._concurrentMax = _concurrency;
}
_lastStartTime = currentTime;
_sumOfOutstandingStartTimes += currentTime;
pending = checkForPending();
}
if (pending != null)
{
pending.deliver();
}
return new CallCompletionImpl(currentTime);
}
Does this mean that all these operations e.g. +=, ++, > etc. requires the JVM to interact with main memory repeatedly? If so, can I use local variables to cache them (preferably stack allocation for primitives) and perform operations and in the end assign them back to the instance variables? Will that help to optimise performance of this block?
I have such blocks in other places as well. On running a JProfiler, it has been observed that most of the time threads are in WAITING state and throughput is also very low. Hence the optimisation necessity.
Appreciate any help here.
synchronizedblock. i.e. the opening{and closing}are memory barriers (acquiring and releasing the lock), but within that block the normal rules apply. The normal rules for non-volatilevars are like in C++: compiler can keep private copies / temporaries and do full optimization. I don't really know Java so not posting this as an answer in case my assumptions are wrong.synchronized(lock). I think you're going to need some outside help. Based on the code it looks like yourtrackeris the bottleneck, but it's hard to know why without seeing the Tracker code (and whether there might be a way to avoid or lessen the bottleneck).lock, that it's no surprise if the throughput is bad. Finally as a sidenote, the code style shows that it wasn't written by someone who writes primarily Java. It's also hard to see what exactly is the thread-unsafe part that's being guarded bysyncblocks, or if it's just being used "for safety" in too many places.