I know there are many questions asked on this but in my case i have it in a synchronised block and i am sure that nobody will be changing my array list.. But still i get this exception SOMETIMES if i am using for-each loop.. Why ?
Here is my code snippet
final static Object mLock = new Object();
private static ArrayList<ConnectionAndAuthCallback> mCallbacks;
private void callAuthCallbacks() {
synchronized (mLock) {
if (mCallbacks != null)
for (ConnectionAndAuthCallback calback : mCallbacks) { //here i get exception
calback.onAuthentication(mToken, calback.intent);
}
}
}
here is the code i do on Callback
#Override
public void onAuthentication(String token, Intent intent) {
web.loadUrl("xyz.com");
//unregister so that we wong get any exception or some more callbacks
SameClass.unRegisterAuthCallbacks(this);
}
and in Unregister function
public static void unRegisterAuthCallbacks(ConnectionAndAuthCallback callback) {
synchronized (mLock) {
if (mCallbacks != null)
if (mCallbacks.contains(callback)) {
mCallbacks.remove(callback); // This causing problem ?? In same thread "syncronised" wont work ??
}
}
}
You can't perform modifications on an ArrayList or remove() in this case that you are currently reading out of or looping through. Use iterators instead.
Check out this link.
And this link.
Answer was, In the same thread synchronised(){} wont work.
Even if you think it works then there might be a dead lock.
In my case i was removing callback object from ArrayList in the same thread where i called callback.
Related
We have been looking at a threading error for a while and are not sure how this is possible. Below is a minimized example from our code. There is a cache holding data retrieved from a database (or: "a lengthy synchronous operation", as far as this example is concerned). There is a thread for reloading the cache, while other threads try to query the cache. There is a period of time when the cache is null, waiting to be reloaded. It should not be queryable during this time, and we tried to enforce this by synchronizing the methods that access the cache - both for reading and writing. Yet if you run this class for a while, you will get NPEs in search(). How is this possible?
Java docs state that "it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object".
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CacheMultithreading01 {
private long dt = 1000L;
public static void main(String[] args) {
CacheMultithreading01 cm = new CacheMultithreading01();
cm.demonstrateProblem();
}
void demonstrateProblem() {
QueryableCache cache = new QueryableCache();
runInLoop("Reload", new Runnable() {
#Override
public void run() {
cache.reload();
}
});
runInLoop("Search", new Runnable() {
#Override
public void run() {
cache.search(2);
}
});
// If the third "runInLoop" is commented out, no NPEs
runInLoop("_Clear", new Runnable() {
#Override
public void run() {
cache.clear();
}
});
}
void runInLoop(String threadName, Runnable r) {
new Thread(new Runnable() {
#Override
public synchronized void run() {
while (true) {
try {
r.run();
} catch (Exception e) {
log("Error");
e.printStackTrace();
}
}
}
}, threadName).start();
}
void log(String s) {
System.out.format("%d %s %s\n", System.currentTimeMillis(), Thread
.currentThread().getName(), s);
}
class QueryableCache {
private List<Integer> cache = new ArrayList<>();
public synchronized void reload() {
clear();
slowOp(); // simulate retrieval from database
cache = new ArrayList<>(Arrays.asList(1, 2, 3));
}
public synchronized void clear() {
cache = null;
}
public synchronized Integer search(Integer element) {
if (cache.contains(element))
return element;
else
return null;
}
private void slowOp() {
try {
Thread.sleep(dt);
} catch (InterruptedException e) {
}
}
}
}
//java.lang.NullPointerException
//at examples.multithreading.cache.CacheMultithreading01$QueryableCache.search(CacheMultithreading01.java:73)
//at examples.multithreading.cache.CacheMultithreading01$2.run(CacheMultithreading01.java:26)
//at examples.multithreading.cache.CacheMultithreading01$4.run(CacheMultithreading01.java:44)
//at java.lang.Thread.run(Thread.java:745)
We do not understand why the NPEs can happen even though the code is synchronized. We also do not understand why the NPEs stop happening if we comment out the third call to runInLoop (the one that does cache.clear).
We have also tried to implement locking using a ReentrantReadWriteLock - and the result is the same.
Since you don't have any more advanced locking, you can call clear() and search() consecutively. That will obviously cause a NPE.
Calling reload() and search() won't cause problems, since in reload the cache is cleared, then rebuilt, inside a synchronized block, preventing other (search) operations from being executed in between.
Why is there a clear() method that will leave cache in a "bad" state (which search() doesn't even check for)?
You have to check in the search method if cache is null. Otherwise calling contains on it in search can throw a NullPointerException in the case that you have previously set cache to null in the clear-method.
Synchronization is working as correctly.
The problem is that the method clear puts cache to null. And there is no guarantee that reload method will be called before search.
Also, note that the method reload, it's not releasing the lock. So, when you are waiting for the slowOp to finish, the other methods can't execute.
"There is a period of time when the cache is null, waiting to be reloaded."
This is your problem: clear sets things to null, and then returns, releasing the synchronization lock, allowing someone else to access.
It would be better to make the "new" assignment atomic and not clear().
Assuming that slowOp() needs to return data for the cache (private List<Integer> slowOp()) you retrieve that data before assigning it
ArrayList<Integer> waitingForData = slowOp();
cache = watingForData;
This 'updates' the cache only after the data is available. Assignment is an atomic operation, nothing can access cache while the reference is being updated.
Three different threads invoking clear() search() and reload() of the cache without a definitive interleaving. Since the interleaving doesn't gurantees the the sequence of lock being obtained for the clear() and search() threads there could be chances where the search thread is getting the lock over the object just after the clear() thread. In that case the search would result in the NullPointerException.
You may have to check for the cache equal to null in the search object and may be do a reload() from within the search() method. This would gurantee the search result or return null as applicable.
I've got an ArrayList which is being instantiated and populated on the background thread (I use it to store the Cursor data). At the same time it can be accessed on the main thread and iterated through using foreach. So this obviously may result in throwing an exception.
My question is what's the best practice to make this class field thread-safe without copying it every time or using flags?
class SomeClass {
private final Context mContext;
private List<String> mList = null;
SomeClass(Context context) {
mContext = context;
}
public void populateList() {
new Thread(new Runnable() {
#Override
public void run() {
mList = new ArrayList<>();
Cursor cursor = mContext.getContentResolver().query(
DataProvider.CONTENT_URI, null, null, null, null);
try {
while (cursor.moveToNext()) {
mList.add(cursor.getString(cursor.getColumnIndex(DataProvider.NAME)));
}
} catch (Exception e) {
Log.e("Error", e.getMessage(), e);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
}).start();
}
public boolean searchList(String query) { // Invoked on the main thread
if (mList != null) {
for (String name : mList) {
if (name.equals(query) {
return true;
}
}
}
return false;
}
}
In general it is a very bad idea to operate concurrently on a datastructure that is not thread-safe. You have no guarantee that the implementation will not change in the future, which may severly impact the runtime behavior of the application, i.e. java.util.HashMap causes infinite loops when being concurrently modified.
For accessing a List concurrently, Java provides the java.util.concurrent.CopyOnWriteArrayList. Using this implementation will solve your problem in various ways:
it is thread safe, allowing concurrent modifications
iterating over snapshots of the list is not affected by concurrent add operations, allowing concurrently adding and iterating
it's faster than synchronization
Alternatively, if not using a copy of the internal array is a strict requirement (which I can't imagine in your case, the array is rather small as it only contains object references, which can be copied in memory quite efficiently), you may synchronize the access on the map.
But that would require the Map to be initialized properly, otherwise your code may throw a NullPointerException because the order of thread-execution is not guaranteed (you assume the populateList() is started before, so the list gets initialized.
When using a synchronized block, choose the protected block wisely. In case you have the entire content of the run() method in a synchronized block, the reader thread has to wait until the results from the cursor are processed - which may take a while - so you actually loose all concurrency.
If you decide to go for the synchronized block, I'd make the following changes (and I don't claim, they are perfectly correct):
Initialize the list field so we can synchronize access on it:
private List<String> mList = new ArrayList<>(); //initialize the field
Synchronize the modification operation (add). Do not read the data from the cursor inside the synchronization block because if its a low latency operation, the mList could not be read during that operation, blocking all other threads for quite a while.
//mList = new ArrayList<>(); remove that line in your code
String data = cursor.getString(cursor.getColumnIndex(DataProvider.NAME)); //do this before synchronized block!
synchronized(mList){
mList.add(data);
}
The read iteration must be inside the synchronization block, so no element gets added, while being iterated over:
synchronized(mList){
for (String name : mList) {
if (name.equals(query) {
return true;
}
}
}
So when two threads operate on the list, one thread can either add a single element or iterate over the entire list at a time. You have no parallel execution on these parts of the code.
Regarding the synchronized versions of a List (i.e. Vector, Collections.synchronizedList()). Those might be less performant because with synchronization you actually lose prallel execution as only one thread may run the protected blocks at a time. Further, they might still be prone to ConcurrentModificationException, which may even occur in a single thread. It is thrown, if the datastructure is modified between iterator creation and iterator should proceed. So those datastructures won't solve your problem.
I do not recommend manualy synchronization as well, because the risk of simply doing it wrong is too high (synchronizing on the wrong or different monitory, too large synchronization blocks, ...)
TL;DR
use a java.util.concurrent.CopyOnWriteArrayList
Use Collections.synchronizedList(new ArrayList<T>());
Ex:
Collections.synchronizedList(mList);
java synchronized block http://www.tutorialspoint.com/java/java_thread_synchronization.htm
class SomeClass {
private final Context mContext;
private List<String> mList = null;
SomeClass(Context context) {
mContext = context;
}
public void populateList() {
new Thread(new Runnable() {
#Override
public void run() {
synchronized(SomeClass.this){
mList = new ArrayList<>();
Cursor cursor = mContext.getContentResolver().query(
DataProvider.CONTENT_URI, null, null, null, null);
try {
while (cursor.moveToNext()) {
mList.add(cursor.getString(cursor.getColumnIndex(DataProvider.NAME)));
}
} catch (Exception e) {
Log.e("Error", e.getMessage(), e);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
}
}).start();
}
public boolean searchList(String query) { // Invoked on the main thread
synchronized(SomeClass.this){
if (mList != null) {
for (String name : mList) {
if (name.equals(query) {
return true;
}
}
}
return false;
}
}
}
You could use a Vector which is the thread-safe equivalent of ArrayList.
EDIT: Thanks to Fildor's comment, I now know this doesn't avoid ConcurrentModificationException from being thrown using multiple threads:
Only single calls will be synchronized. So one add cannot be called while another thread is calling add, for example. But altering the list will cause the CME be thrown while iterating on another thread. You can read the docs of iterator on that topic.
Also interesting:
Why is Java Vector class considered obsolete or deprecated?
Vector vs Collections.synchronizedList(ArrayList)
Long story short: DO NOT use Vector.
I have a Thread that only has to work when a certain circumstance comes in. Otherwise it just iterates over an empty infinite loop:
public void run() {
while(true) {
if(ball != null) {
// do some Calculations
}
}
}
Does it affect the performance when the loop actually does nothing but it has to check if it has to do the calculation every iteration?
Only creating a this Thread when needed is not an option for me, because my class which implements Runnable is a visual object which has be shown all the time.
edit: so is the following a good solution? Or is it better to use a different method (concerning performance)?
private final Object standBy = new Object();
public void run() {
while(true) {
synchronized (standBy) {
while(ball != null) // should I use while or if here?
try{ standBy.wait() }
catch (InterruptedException ie) {}
}
if(ball != null) {
// do some Calculations
}
}
public void handleCollision(Ball b) {
// some more code..
ball = b;
synchronized (standBy) {
standBy.notify();
}
}
You might want to consider putting the thread to sleep and only waking it up only when your 'ball' variable becomes true. There are multiple ways of doing this, from using the very low level, wait and notify statements to using the java.util.concurrent classes which provide a less error prone way of doing this. Have a look at the documentation for the condition interface. A data structure like a BlockingQueue would also be a solution.
Yes it does. This is the most simple implementation of busy waiting, and should be avoided whenever possible. Use wait/notify or java.util.concurrent mechanisms. Maybe you should be more specific about what exactly you want to achieve to get more useful responses.
Yes, it will certainly affect performance. To increase performance, you can consider putting in a bit of a time delay (say 500ms or 1000ms or even higher) in your code depending how crucial timing is to you.
Share a BlockingQueue between your threads.
class Producer implements Runnable {
private final BlockingQueue queue;
Producer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { queue.put(produce()); }
} catch (InterruptedException ex) { ... handle ...}
}
Object produce() { ... }
}
class Consumer implements Runnable {
private final BlockingQueue queue;
Consumer(BlockingQueue q) { queue = q; }
public void run() {
try {
while (true) { consume(queue.take()); }
} catch (InterruptedException ex) { ... handle ...}
}
void consume(Object x) { ... }
}
I found the following interesting thing. In task manager, running that infinite loop like that, would consume 17% of my CPU. Now, if I added a simple
Thread.sleep(1)
inside the loop, which is only one milisecond, the CPU use dropped to almost zero as if I was not using the program, and the response time of the program was still pretty good on average (in my case it needed to reply things fast)
I am sorting my list data after every modification but since several threads could call the sorting method block, I decided to put it in a synchronized block. My code is as shown below. Problem is, despute the synchronized block, I am still getting 'ConcurrentModificationExceptio' on the line Collections.sort(storageBckupData.get(msg.what).getTotalItems(),new BackupDataComparator());. Any reason why I keep getting this?
class IncomingHandler extends Handler {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
default:
synchronized(LOCK) {
while(inUse) {
try {
LOCK.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
inUse = true;
Collections.sort(storageBckupData.get(msg.what).getTotalItems(),new BackupDataComparator());
inUse = false;
LOCK.notifyAll();
}
notifyDataSetChanged();
super.handleMessage(msg);
}
}
}
ConcurrentModificationException is not about whether you have synchronized or not, its when the collection detects a modification being done concurrently with something that does not allow it. For example you might have (somewhere else in your code which you are not showing) an iterator going through the list of items. Its about protecting the integrity of the collection.
What is happening in the other thread? Is it going through the list in parallel?
Draw a Sequence Diagram of both threads and you should clearly find what one thread is doing in parallel of the other.
Also, do you actually need to do that locking? You can get a synchronized collection through methods such as Collections.synchronizedList()
Why don't you use an appropriate data structure that takes care of sorting more efficiently? If each item is unique you could use a SortedSet implementation such as TreeSet.
I have a class proposing translations utilities. The translations themselves should be reloaded every 30 minutes. I use Spring Timer support for that. Basically, my class looks like :
public interface Translator {
public void loadTranslations();
public String getTranslation(String key);
}
loadTranslations() can be pretty long to run, so while it is running the old translations are still available. This is done by loading the translations in a local Map and just changing the reference when all translations are loaded.
My problem is : how do I make sure that when a thread is already loading translations, is a second one also tries to run, it detects that and returns immediately, without starting a second update.
A synchronized method will only queue the loads ... I'm still on Java 1.4, so no java.util.concurrent.
Thanks for your help !
Use some form of locking mechanism to only perform the task if it is not already in progress. Acquiring the locking token must be a one-step process. See:
/**
* #author McDowell
*/
public abstract class NonconcurrentTask implements Runnable {
private boolean token = true;
private synchronized boolean acquire() {
boolean ret = token;
token = false;
return ret;
}
private synchronized void release() {
token = true;
}
public final void run() {
if (acquire()) {
try {
doTask();
} finally {
release();
}
}
}
protected abstract void doTask();
}
Test code that will throw an exception if the task runs concurrently:
public class Test {
public static void main(String[] args) {
final NonconcurrentTask shared = new NonconcurrentTask() {
private boolean working = false;
protected void doTask() {
System.out.println("Working: "
+ Thread.currentThread().getName());
if (working) {
throw new IllegalStateException();
}
working = true;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (!working) {
throw new IllegalStateException();
}
working = false;
}
};
Runnable taskWrapper = new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
shared.run();
}
}
};
for (int i = 0; i < 100; i++) {
new Thread(taskWrapper).start();
}
}
}
I am from a .net background(no java experience at all), but you could try a simple static flag of some sort that checks at the beginning of the method if its alrady running. Then all you need to do is make sure any read/write of that flag is synchronized. So at beginning check the flag, if its not set, set it, if it is set, return. If its not set, run the rest of the method, and after its complete, unset it. Just make sure to put the code in a try/finally and the flag iunsetting in the finally so it always gets unset in case of error. Very simplified but may be all you need.
Edit: This actually probably works better than synchronizing the method. Because do you really need a new translation immediately after the one before it finishes? And you may not want to lock up a thread for too long if it has to wait a while.
Keep a handle on the load thread to see if it's running?
Or can't you just use a synchronized flag to indicate if a load is in progress?
This is actually identical to the code that is required to manage the construction of a Singleton (gasp!) when done the classical way:
if (instance == null) {
synchronized {
if (instance == null) {
instance = new SomeClass();
}
}
}
The inner test is identical to the outer test. The outer test is so that we dont routinely enter a synchronised block, the inner test is to confirm that the situation has not changed since we last made the test (the thread could have been preempted before entering Synchronized).
In your case:
if (translationsNeedLoading()) {
synchronized {
if (translationsNeedLoading()) {
loadTranslations();
}
}
}
UPDATE: This way of constructing a singleton will not work reliably under your JDK1.4. For explanation see here. However I think you are you will be OK in this scenario.