My component integrates to a third-party component. I have to override the onTick() method which is called by a high-priority Thread of the third-party component. Sample code:
#Override
public void onTick() {
// do many useful operations
}
In certain scenarios, this onTick() method should not perform those "many useful operations", because their results are discarded. In fact, the functionality of onTick() is not needed at all in that case, but the third-party component does not offer any "pause" or "sleep" functionality. It calls onTick() all the time. This means that CPU time is used up unnecessarily in these special periods.
The most straightforward solution would be to send a signal to onTick() and make its thread sleep via an Object.wait() in a proper synchronized block. However, the documentation of the third-party component states that its Thread should not be sent to waiting state arbitrarily.
Is there any solution to save CPU resources in this case? That is, to let others use the CPU? I created the following solution, but I'm not sure it allows to save any CPU. (Nonetheless, at least, it should save other resources used by the "useful operations" section of onTick()).
#Override
public void onTick() {
// mJustUnpaused is volatile. Race condition, but probably harmless (?)
if (mJustUnpaused) {
mJustUnpaused = false;
// THREAD_PRIORITY_DISPLAY is the original
// priority used by the 3rd party Thread
Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
}
if (!mRunningAllowed) {
return;
}
if (mPauseRequested) { // mPauseRequested is declared as volatile
synchronized (mPauseLock) {
if (mRunningAllowed && mPauseRequested) {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
mRunningAllowed = false;
mPauseLock.notify();
}
}
return;
}
// do many useful operations
}
The methods for pausing/unpausing (the first one is blocking, the second isn't):
public void pauseWork() {
synchronized (mPauseLock) {
if (mRunningAllowed && !mPauseRequested) {
mPauseRequested = true;
while (mRunningAllowed) {
try {
mPauseLock.wait();
} catch (InterruptedException e) {}
}
} else {
Log.d("RPT", "Already paused or pausing");
}
}
}
public void unpauseWork() {
synchronized (mPauseLock) {
if (!mRunningAllowed) {
mRunningAllowed = true;
mPauseRequested = false;
mJustUnpaused = true;
} else {
Log.d("RPT", "No need to unpause");
}
}
}
Three questions:
Is there a better way to save some CPU time?
Regardless of everything else, is my above code correct (in terms of synchronization and other programming aspects)?
Slightly off-topic, but I don't think it deserves a dedicated question: does changing a Thread's priority have any significant overhead? Are there any general guidelines when such an act can be done? (e.g. how often can it be done, etc.)
Is there a better way to save some CPU time?
I wouldn't even bother with what's there. I agree with Chris Stratton: just avoid doing the actual work, and delete the rest of the other code shown above. Then, use Traceview to see whether or not the overhead of your do-nothing onTick() calls is noticeable. Most likely, it will not be.
But I want to change the thread priority as well
That's not a good idea, as it is not your thread, if I understand the scenario properly. Moreover, I believe that you are going to be called ~300 times regardless, as if the library is coded to call you ~30 times a second, it is likely using a Timer or something else that should be relatively immune to thread priority.
Regardless of everything else, is my above code correct (in terms of synchronization and other programming aspects)?
Personally, I'd use stuff from java.util.concurrent and java.util.concurrent.atomic, rather than low-level wait()/notify()/volatile. Doug Lea is smarter than I am. :-)
Related
I am to download data from the server, with a maximum of 3 attempts if the download fails.
public class DownloadFile {
private boolean isSuccessful;
public DownloadFile() {
int attempt = 0;
while(!isSuccessful && (attempt++ < 3)) {
DownloadFileThread.start();
while (DownloadFileThread.isAlive());
}
}
private Thread DownloadFileThread = new Thread() {
public void run() {
try {
// download file from server
isSuccessful = true;
} catch (Exception e) {
isSuccessful = false;
}
}
}
}
As you can see in the above example, I have an empty while loop in (what would be) line 10 to force guarantee isSuccessful is assignment a value based on the outcome of the DownloadFileThread before checking the condition in the while loop again.
Is it considered bad practice to do such a thing? Is there better approach or a correct way to do this?
While the above code does produce a valid result, I am not exactly proud of the code I have written...
Yes, in this case it is a bad practice, because Java offers better mechanisms to wait for completion of a thread: Thread.join(), or consider using more modern features like CompletableFuture or an ExecutorService that allows you to wait for a task to complete.
Using an empty loop to wait will consume a lot of CPU power unnecessarily, which might mean other tasks on your system will perform slower than they could otherwise.
Not necessarily, but in this case this is a busy wait which is bad practice especially in multi-threaded programs. It keeps the CPU busy and in your case interferes with DownloadFileThread.
In your case the while loop will execute permanently stealing process time from other things, maybe also from your download thread.
If you simply want to wait until your download is done, why don´t you use Thread.join() ?
It´s blocking, meaning that you won´t be able to execute anything in your main-thread until the DownloadThread is done but your while loop does this as well in this case and use more system resources on top.
I found a piece of code where the thread seems to starve. Below is a simplified example. Is this an example for starvation? What is the reason why the thread does not terminate?
Note: Changing the sleep to 1 will sometimes result in termination. The commented out Thread.yield() would solve the problem (for me).
public class Foo {
public static boolean finished = false;
public static void main(String[] args) {
Runnable worker = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finished = true;
}
};
new Thread(worker).start();
while (!finished) {
// Thread.yield();
}
}
}
You probably need to get informed on the Java Memory Model. Multithreading isn't just about interleaving the actions of threads; it is about the visibility of actions by one thread to another.
At the bottom of this issue lies the need for aggressive optimization in the face of concurrency: any mechanism which ensures memory coherency between threads is expensive, and much (most) of the data is not shared between threads. Therefore the data not explicitly marked volatile, or protected by locks, is treated as thread-local by default (without strict guarantees, of course).
In your case, finished is such a variable which is allowed to be treated as thread-local if it pleases the runtime. It does please it because the
while (!finished);
loop can be rewritten to just
if (!finished) while (true);
If you did any important work inside the loop, it would perform a bit better because the read of finished wouldn't be needlessly repeated, thus possibly destroying one whole CPU cache line.
The above discussion should be enough to answer your immediate question, "is this starvation": the reason the loop doesn't finish is not starvation, but the inability to see the write by the other thread.
There's no starvation here, because you're not doing any work. Starvation means various threads are trying to access the same, limited set of resources. What are the resources each thread is trying to access here? They're not "eating" anything, so they can't starve.
I have been using this pattern for a while, but I only recently came to think that it might not be OK to do this. Basically, I use some variant of this pattern:
public class SampleJavaAsync
{
public SampleJavaAsync() { }
private boolean completed;
public void start()
{
new Thread(new Runnable() {
#Override
public void run() {
//... do something on a different thread
completed = true;
}
}).start();
}
public void update()
{
if (!completed) return;
//... do something else
}
}
*The user is responsible for making sure start is only called once. update is called wherever and whenever.
I've always assumed this is threadsafe in Java, because even though nothing is strictly synchronized, I only ever set completed to true. Once it has been observed to be true, it will not reset to false. It is initialized to false in the constructor, which is by definition thread safe (unless you do something stupid in it). So, is it thread safe to use unresettable flags in this way? (And if so, does it even provide any performance benefits?)
Thanks
Java: it's feasible for update() to not see the update to completed that has already happened. Unless you mark it volatile, the JVM is permitted to do all sorts of things in the name of optimization (namely reordering reads and writes as it sees fit), meaning you could feasibly hit a state where the thread running update() NEVER sees that completed has changed, because it's not marked volatile, and it thinks it can optimize away that pesky write (or defer it).
You would at least run the risk of having inconsistency when it's first set, where, e.g. a call to update() on the same thread could see a different value than the same call from another thread, at the same time.
Better explained:
http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html
Or, if you're really curious about concurrency in Java, buy a copy of JCIP:
http://jcip.net.s3-website-us-east-1.amazonaws.com/
Question: What is the cost of re-entering a synchronized block when the monitor is already locked?
For example:
Object lock;
void outer()
{
synchronized (lock)
{
innerOne();
innerTwo();
}
}
void innerOne() { synchronized (lock) { /* ... */ } }
void innerTwo() { synchronized (lock) { /* ... */ } }
The intention of the above is that innerOne and innerTwo are always called while the thread is synchronised on lock.
If there is a non-negligible cost is there any method that can be called to put in an assert statement? The closest I can find is to call lock.notify(), and catch IllegalMonitorStateException, e.g.
boolean isMonitorHeld(final Object object)
{
try { object.notify(); return true }
catch (final IllegalMonitorStateException e) { return false; }
}
Which would be used like:
void innerOne() { assert isMonitorHeld(lock); /* ... */ }
Are there any comments on the style of the two options, or any alternatives?
EDIT
I'm hoping for more comprehensive answers than just 'time it and see'. I don't have the ability to foresee all of the potential situations my code could encounter and then even create a test to exhibit these situations. I'd like to understand how the synchronisation mechanism works to understand how it might perform in different circumstances. I understand synchronisation may be implemented differently on the different platforms. In which case is it different (primarily on Solaris and Linux OSes)?
Intuitively, I don't believe that re-entering a synchronised block will have a noticeable cost as most of the articles I can find imply that uncontended locks are cheap. However, it doesn't feel right to add the synchronised blocks in these methods as it gives the impression they can be called without having first synchronised on the lock. The assert gives a better idea of the intention, but it looks like a fairly ugly hack. I'd like to know if there's a good reason that there isn't a more legitimate alternative.
So your question is asking one thing, and then the body of your question is asking something else. I can most certainly say your algorithm to test if a thread hold a lock will be very slow. Much slower than just not checking. Throwing exceptions like this is expensive. Rule number one about exceptions. Don't use Exceptions for regular flow control in your program. Exceptions are a form of control flow structure, but you should only use them for error flow control. Mainly because whenever you throw an exception it must gather up the stack trace to place that into the exception. That is an expensive operation. You should definitely use exceptions, but only for what they are designed for: error flow control.
If you want to test if the currentThread holds a lock you should use Thread.holdsLock(Object monitor)
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#holdsLock(java.lang.Object)
As for what is the cost of re-entering into a synchronize block for the currentThread is already a holder. I don't have a very detailed answer for that. I suspect its whatever the cost of calling holdsLock is. That's probably the first check, and if it returns false then there is more cost with requesting this thread be add to the list of threads waiting on this object monitor. If it's true it jumps right into the block. Java threading, if it wants to be performant, the answer to this question better be fast as hell for the lock owner. For threads not owning a lock its certainly more expensive. If there is an answer to what the exact algorithm is I bet its in the "Taming Threads" book or Java spec.
Measure it. On my system there might not be a difference. On yours there might. The system you deploy to might be more different still.
I have a process A that contains a table in memory with a set of records (recordA, recordB, etc...)
Now, this process can launch many threads that affect the records, and sometimes we can have 2 threads trying to access the same record - this situation must be denied. Specifically if a record is LOCKED by one thread I want the other thread to abort (I do not want to BLOCK or WAIT).
Currently I do something like this:
synchronized(record)
{
performOperation(record);
}
But this is causing me problems ... because while Process1 is performing the operation, if Process2 comes in it blocks/waits on the synchronized statement and when Process1 is finished it performs the operation. Instead I want something like this:
if (record is locked)
return;
synchronized(record)
{
performOperation(record);
}
Any clues on how this can be accomplished?
Any help would be much appreciated.
Thanks,
One thing to note is that the instant you receive such information, it's stale. In other words, you could be told that no-one has the lock, but then when you try to acquire it, you block because another thread took out the lock between the check and you trying to acquire it.
Brian is right to point at Lock, but I think what you really want is its tryLock method:
Lock lock = new ReentrantLock();
......
if (lock.tryLock())
{
// Got the lock
try
{
// Process record
}
finally
{
// Make sure to unlock so that we don't cause a deadlock
lock.unlock();
}
}
else
{
// Someone else had the lock, abort
}
You can also call tryLock with an amount of time to wait - so you could try to acquire it for a tenth of a second, then abort if you can't get it (for example).
(I think it's a pity that the Java API doesn't - as far as I'm aware - provide the same functionality for the "built-in" locking, as the Monitor class does in .NET. Then again, there are plenty of other things I dislike in both platforms when it comes to threading - every object potentially having a monitor, for example!)
Take a look at the Lock objects introduced in the Java 5 concurrency packages.
e.g.
Lock lock = new ReentrantLock()
if (lock.tryLock()) {
try {
// do stuff using the lock...
}
finally {
lock.unlock();
}
}
...
The ReentrantLock object is essentially doing the same thing as the traditional synchronized mechanism, but with more functionality.
EDIT: As Jon has noted, the isLocked() method tells you at that instant, and thereafter that information is out of date. The tryLock() method will give more reliable operation (note you can use this with a timeout as well)
EDIT #2: Example now includes tryLock()/unlock() for clarity.
I found this, we can use Thread.holdsLock(Object obj) to check if an object is locked:
Returns true if and only if the current thread holds the monitor lock on the specified object.
Note that Thread.holdsLock() returns false if the lock is held by something and the calling thread isn't the thread that holds the lock.
Whilst the above approach using a Lock object is the best way to do it, if you have to be able to check for locking using a monitor, it can be done. However, it does come with a health warning as the technique isn't portable to non Oracle Java VMs and it may break in future VM versions as it isn't a supported public API.
Here is how to do it:
private static sun.misc.Unsafe getUnsafe() {
try {
Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void doSomething() {
Object record = new Object();
sun.misc.Unsafe unsafe = getUnsafe();
if (unsafe.tryMonitorEnter(record)) {
try {
// record is locked - perform operations on it
} finally {
unsafe.monitorExit(record);
}
} else {
// could not lock record
}
}
My advice would be to use this approach only if you cannot refactor your code to use java.util.concurrent Lock objects for this and if you are running on an Oracle VM.
While the Lock answers are very good, I thought I'd post an alternative using a different data structure. Essentially, your various threads want to know which records are locked and which aren't. One way to do this is to keep track of the locked records and make sure that data structure has the right atomic operations for adding records to the locked set.
I will use CopyOnWriteArrayList as an example because it's less "magic" for illustration. CopyOnWriteArraySet is a more appropriate structure. If you have lots and lots of records locked at the same time on average then there may be performance implications with these implementations. A properly synchronized HashSet would work too and locks are brief.
Basically, usage code would look like this:
CopyOnWriteArrayList<Record> lockedRecords = ....
...
if (!lockedRecords.addIfAbsent(record))
return; // didn't get the lock, record is already locked
try {
// Do the record stuff
}
finally {
lockedRecords.remove(record);
}
It keeps you from having to manage a lock per record and provides a single place should clearing all locks be necessary for some reason. On the other hand, if you ever have more than a handful of records then a real HashSet with synchronization may do better since the add/remove look-ups will be O(1) instead of linear.
Just a different way of looking at things. Just depends on what your actual threading requirements are. Personally, I would use a Collections.synchronizedSet( new HashSet() ) because it will be really fast... the only implication is that threads may yield when they otherwise wouldn't have.
Another workaround is (in case of you didnt have chance with the answers given here )is using timeouts. i.e. below one will return null after 1 second hanging:
ExecutorService executor = Executors.newSingleThreadExecutor();
//create a callable for the thread
Future<String> futureTask = executor.submit(new Callable<String>() {
#Override
public String call() throws Exception {
return myObject.getSomething();
}
});
try {
return futureTask.get(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
//object is already locked check exception type
return null;
}
I needed to also find a solution to this, so searched the Java Concurrency API and came across StampedLock. The project is using Java 8.
I am working in a heavily-threaded asynchronous data service that communicates with a native library and contains long-living configuration objects, necessitating sometimes-complex concurrency logic; thankfully this turned out to be relatively simple with the StampedLock class.
StampedLock has a method called tryOptimisticRead which does not wait, it just returns the status in the form of a long-time time stamp, where zero (0) indicates an exclusive lock is held. I then do delay for up to a second but you could just use the function without any sort of delay.
Here's how I'm detecting whether or not there's an exclusive lock, this paradigm is used in multiple locations and includes error handling:
int delayCount = 0;
//Makes sure that if there is data being written to this field at
// this moment, wait until the operation is finished writing the
// updated data.
while (data1StampedLock.tryOptimisticRead() == 0)
{
try
{
delay(WRITE_LOCK_SHORT_DELAY);
delayCount += 1;
}
catch (InterruptedException e)
{
logError("Interrupted while waiting for the write lock to be
released!", e);
Thread.currentThread().interrupt();
//There may be an issue with the JVM if this occurs, treat
// it like we might crash and try to release the write lock.
data1StampedLock.tryUnlockWrite();
break;
}
if (delayCount * WRITE_LOCK_SHORT_DELAY > TimeUnit.SECONDS.toMillis(1))
{
logWarningWithAlert("Something is holding a write lock on" +
" the data for a very, very long time (>1s). This may" +
" indicate a problem that could cause cascading" +
" problems in the near future." +
" Also, the value for the data that is about to be" +
" retrieved could potentially be invalid.");
break;
}
}
long nonExclusiveLockStamp = data1StampedLock.readLock();
Data data1NonVolatile = data1;
data1StampedLock.unlockRead(nonExclusiveLockStamp);
return data1NonVolatile;
The read locks on a StampedLock are non-exclusive and are like reading from a thread-safe Map or HashTable, where it is multi-read/single-write.
Here is how I am using the exclusive lock to communicate to other threads that the instance data is being written to:
long d1LockStamp = data1StampedLock.writeLock();
this.data1 = data1;
data1StampedLock.unlockWrite(d1LockStamp);
So if you wanted to only check whether or not something is locked at any given moment, you need only something simple like the following statement to get the status:
boolean data1IsLocked = data1StampedLock.tryOptimisticRead() == 0;
Then check the value of that boolean.
There are, of course, the caveats and Here Be Dragons information mentioned in other answers (namely that the information is immediately stale), but if you really need to lock something and check that lock from another thread, this seemed to me to be the most reasonable, safe, and effective way that uses the java.util.concurrency package with no external dependencies.
Thanks for this, it helped me out solving a race condition. I changed it a little to wear both belt and suspenders.
So here is my suggestion for AN IMPROVEMENT of the accepted answer:
You can ensure that you get safe access to the tryLock() method by doing something like this:
Lock localLock = new ReentrantLock();
private void threadSafeCall() {
boolean isUnlocked = false;
synchronized(localLock) {
isUnlocked = localLock.tryLock();
}
if (isUnlocked) {
try {
rawCall();
}
finally {
localLock.unlock();
}
} else {
LOGGER.log(Level.INFO, "THANKS! - SAVED FROM DOUBLE CALL!");
}
}
This would avoid the situation where you might get two calling tryLock() at the almost same time, causing the return to be potentially doubt full. I'd like to now if I'm wrong, I might be over cautios here. But hey! My gig is stable now :-)..
Read more on my development issues at my Blog.