The another question is about synchronized. I have also a run() in class Note,because i want to output each element in notes every 5 minutes. But i get always exception:java.util.ConcurrentModificationException,if i try to make more meetings in main. so i applay synchronized to the list notes which may be added a new meeting when i iterate over notes.My run method like this:
Is it correct way hier on list notes to synchronized to prevent ConcurrentModificationException ?(In my program it works.I get never this exception now)
A Meeting class and Note class may likes this:
public class Meeting{
public Meeting(Note note_1,Note note_2){
note_1.addElement(this);
note_2.addElement(this);}
//another method hier
}
public class Note implements Runnable{
public final List<Meeting> notes = new ArrayList<Meeting>();
public void addElement(Meeting n){
entries.add(n);
}
#Override
public void run(){
while(true) {
for(Meeting n : notes){
System.out.println(n.toString);}
}
try{ Thread.sleep(10);}
}
}
}
I get always exception error about exception:java.util.ConcurrentModificationException if i try to make more Meeting in main ,So i changes a littel in class Note,likes this :
private static final List<Entry> entries = Collections.synchronizedList(new ArrayList<Entry>());
and in run()
#Override
public void run() {
while(true){
synchronized(notes){
for(Entry n : entries){
//do something
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e ) {
}
}
}
}
From the javadoc
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will thow this exception.
THis means do not change your collection in a loop and iterate over it at the same time even in the same thread.
Read to what #Navi had written.
In a nutshell - NEVER remove/add elements of a collection in for each loop.
I once had that kind of problem and I decided to use http://code.google.com/p/google-collections/
There are some map/filter functions there (if I recall that methods were in Collections2 library).
If you are not willing to make the things right, you can always use the old-school iterator technique.
I've used a CopyOnWriteArrayList before when I encountered this sort of problem.
This makes a complete copy of the underlying array for each write, so it's not very efficient, but I've found it very useful for specific circumstances (e.g. a class which manages specialised event notification to some other classes)
This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException
Related
I have a list
testList= new ArrayList<String>(); // gets initialized once at the very beginning init(). This list never changes. It's static and final.
I have a static method that checks if an input value is in this List :
public static boolean isInList (String var1)
throws InterruptedException {
boolean in = false;
for (String s : testList) {
if (s.equals(var1))
{
in = true;
break;
}
}
return in;
}
I have a lot of threads that use this method concurrently and check if a certain value is in this list. It seems to work fine. However, I'm not sure if this is safe. Am I doing this correctly? Is it thread safe?
It is thread-safe as long as no thread is modifying the list while other threads are reading it.
If you are using iterators over the list, they will "fail-fast" (as in throw ConcurrentModificationException) if the list is modified under them. Other methods of accessing (i.e. get(n)) won't throw an exception but may return unexpected results.
This is all covered in great detail in the Javadoc for List and ArrayList, which you should study carefully.
ArrayList is not a thread safe object. It may works for you now, but in general, when working with threads, you should make sure you're using thread-safe objects that will work with your threads as you expect.
You can use Collections.synchronizedList()
testList = Collections.synchronizedList(new ArrayList<String>());
As long as you can guarantee that no one is writing to the list, it's safe.
Note that even if the list is static and final, the code itself doesn't guarantee that the list is never modified. I recommend using Collections.unmodifiableList() instead, because it guarantees that no element is ever added to or removed from the list.
By the way, you can rewrite your code to this:
public static boolean isInList(String var1) {
for (String s : testList) {
if (Objects.equals(s, var1)) {
return true;
}
}
return false;
}
or just
testList.contains(var1);
The first thread is filling a collection continuously with objects. A second thread needs to iterate over these objects, but it will not change the collection.
Currently I use Collection.synchronized for making it thread-safe, but is there a fast way to doing it?
Update
It's simple: The first thread (ui) continuously writes the mouse position to the ArrayList, as long as the mousebutton is pressed down. The second thread (render) draws a line based on the list.
Use java.util.concurrent.ArrayBlockingQueue.ArrayBlockingQueue implementation of BlockingQueue. It perfectly suits your needs.
It is perfectly suited for producer-consumer cases as that is one in yours.
You can also configure access policy. Javadoc explains access policy like this:
Fair if true then queue accesses for threads blocked on insertion or removal, are processed in FIFO order; if false the access order is unspecified.
Even if you synchronize the list, it's not necessarily thread-safe while iterating over it, so make sure you synchronize on it:
synchronized(synchronizedList) {
for (Object o : synchronizedList) {
doSomething()
}
}
Edit:
Here's a very clearly written article on the matter:
http://java67.blogspot.com/2014/12/how-to-synchronize-arraylist-in-java.html
As mentioned in comments, you need explicit synchronization on this list, because iteration is not atomic:
List<?> list = // ...
Thread 1:
synchronized(list) {
list.add(o);
}
Thread 2:
synchronized(list) {
for (Object o : list) {
// do actions on object
}
}
There are 3 options which I can currently think of to handle concurrency in ArrayList:-
Using Collections.synchronizedList(list) - currently you are using it.
CopyOnWriteArrayList - behaves much like ArrayList class, except that when the list is modified, instead of modifying the underlying array, a new array in created and the old array is discarded. It will be slower than 1.
Creating custom ArrayList class using ReentrantReadWriteLock. You can create a wrapper around ArrayList class. Use read lock when reading/iterating/looping and use write lock when adding elements in array.
For e.g:-
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteList<E> {
private final List<E> list;
private ReadWriteLock lock = new ReentrantReadWriteLock();
private final Lock r =lock.readLock();
private final Lock w =lock.writeLock();
public ReadWriteList(List<E> list){
this.list=list;
}
public boolean add(E e){
w.lock();
try{
return list.add(e);
}
finally{
w.unlock();
}
}
//Do the same for other modification methods
public E getElement(int index){
r.lock();
try{
return list.get(index);
}
finally{
r.unlock();
}
}
public List<E> getList(){
r.lock();
try{
return list;
}
finally{
r.unlock();
}
}
//Do the same for other read methods
}
If you're reading far more often than writing, you can use CopyOnWriteArrayList
Rather than a List will a Set suit your needs?
If so, you can use Collections.newSetFromMap(new ConcurrentHashMap<>())
Sorry if this is a dumb question. But could someone explain me what could happens in a scenario like this?
List<Integer> scores = new Arraylist<>() ;
scores =
Collections.synchronizedList(scores)
public void add(int element) {
...
scores.add(element)
...
}
public String retrieve(int element) {
...
For (Integer e : scores)....
....
Return something
}
Let's assume that this class is a singelton and that scores is global. Multiple thread can add and retrieve the scores at the same time
In this scenario when starting the for loop and at the same time a thread is adding (or removing an element from the list) will it throw a concurrent modification exeption ?
Thank you
Bad things will happen, given the way you've written your example.
Your retrieve() method doesn't have its loop in a synchronized block, and both of your methods are accessing scores directly, instead of using the List returned by the Collections.synchronizedList() method.
If you take a look at the API for Collections.synchronizedList(), you'll notice that it says
In order to guarantee serial access, it is critical that all access to the backing list is accomplished through the returned list.
It is imperative that the user manually synchronize on the returned list when iterating over it:
Failure to follow this advice may result in non-deterministic behavior.
So you might get a ConcurrentModificationException, or something else weird might happen.
Edit
Even if all your access is via the synchronized List, you can still end up getting a ConcurrentModificationException thrown at you if you modify the List while iterating over it in another thread. That's why the Collections.synchronizedList() documentation insists that you manually wrap your iteration inside a block that is synchronized on the List it returns.
The API for ConcurrentModificationException says
For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.
Your add method won't need to be changed, but your retrieve() method should look something like:
public String retrieve(int element) {
// stuff
synchronized (scores) { // prevent scores from being modified while iterating
for (Integer e : scores) {
// looping stuff
}
}
// more stuff
return something;
}
Sample Program
Here's a small sample program which demonstrates the behavior of safe vs unsafe access:
public class Scratch {
private List<Integer> scores = Collections.synchronizedList(new ArrayList<Integer>());
public static void main(String[] args) throws Exception {
final Scratch s = new Scratch();
s.scores.add(1);
s.scores.add(2);
s.scores.add(3);
// keep adding things to the list forever
new Thread(new Runnable() {
#Override
public void run() {
try {
int i=100;
while (true) {
Thread.sleep(100);
s.scores.add(i++);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
System.out.println("This will run fine");
s.safeLoop();
System.out.println("This will cause a ConcurrentModificationException");
s.unsafeLoop();
}
public void safeLoop() throws InterruptedException {
synchronized (scores) {
for (int i : scores) {
System.out.println("i="+i);
Thread.sleep(100);
}
}
}
public void unsafeLoop() throws InterruptedException {
for (int i : scores) {
System.out.println("i="+i);
Thread.sleep(100);
}
}
}
I have two threads modifying the same objects. The objects are custom, non-synchronized objects in an ArrayList (not a vector). I want to make these two threads work nicely together, since they are called at the same time.
Here is the only important method in thread 1.
public void doThread1Action() {
//something...
for(myObject x : MyArrayList){
modify(x);
}
}
Here is a method in thread 2:
public void doThread2Action() {
//something...
for(myObject x : MyArrayList){
modifyAgain(x);
}
}
At the moment, when testing, I occasionally get `ConcurrentModificationExceptions``. (I think it depends on how fast thread 1 finishes its iterations, before thread 2 tries to modify the objects.)
Am I right in thinking that by simply appending synchronized to the beginning of these two methods, the threads will work together in a synchronized way and not try to access the ArrayList? Or should I change the ArrayList to a Vector?
A ConcurrentModificationException does not stem from modifying objects in a collection but from adding / removing from a collection while an iterator is active.
The shared resources is the collection and there must be a third method using and add/remove. To get concurrency right you must synchronize access to the collection resource in all methods that access it.
To avoid overly long synchronized blocks a common pattern may be to copy the collection in a synchronized block and then iterate over it. If you do it this way, be aware the problem you are talking about in first place (concurrent modification of your object) is again in place - but this time you can lock on another resource.
You do not need to synchronize access to the list as long as you don't modify it structurally, i.e. as long as you don't add or remove objects from the list. You also shouldn't see ConcurrentModificationExceptions, because these are only thrown when you structurally modify the list.
So, assuming that you only modify the objects contained in the list, but you do not add or remove or reorder objects on the list, it is possible to synchronize on the contained objects whenever you modify them, like so:
void modifyAgain(MyObject x) {
synchronized(x) {
// do the modification
}
}
I would not use the synchronized modifier on the modifyAgain() method, as that would not allow two distinct objects in the list to be modified concurrently.
The modify() method in the other thread must of course be implemented in the same way as modifyAgain().
You need to sychronsize access to the collection on the same lock, so just using synchronized keyword on the methods (assuming they are in different classes) would be locking on two different objects.
so here is an example of what you might need to do:
Object lock = new Object();
public void doThread1Action(){
//something...
synchronized(lock){
for(myObject x : MyArrayList){
modify(x);
}
}
public void doThread2Action(){
//something...
synchronized(lock){
for(myObject x : MyArrayList){
modifyAgain(x);
}
}
Also you could consider using a CopyOnWriteArrayList instead of Vector
I guess your problem is related to ConcurrentModificationException. This class in its Java docs says:
/**
* This exception may be thrown by methods that have detected
concurrent
* modification of an object when such modification is not
permissible.
*/
In your case, problem is iterator in a list and may modified. I guess by following implementation your problem will sole:
public void doThread1Action()
{
synchronized(x //for sample)
{
//something...
for(myObject x : MyArrayList)
{
modify(x);
}
}
}
and then:
public void doThread2Action()
{
synchronized(x //for sample)
{
//something...
for(myObject x : MyArrayList)
{
modifyAgain(x);
}
}
}
For take better result I want anyone correct my solution.
Given, that add method defination in ArrayList is as follows :-
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
Please find following program to check Thread safety of ArrayList.
package pack4;
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<String>() ;
new AddFirstElementThread(al).start() ;
new RemoveFirstElementThread(al).start() ;
}
}
class AddFirstElementThread extends Thread{
ArrayList<String> list ;
public AddFirstElementThread(ArrayList<String> l) {
list = l ;
}
#Override
public void run() {
while(true){
if(list.size() == 0){
list.add("First element") ;
}
}
}
}
class RemoveFirstElementThread extends Thread{
ArrayList<String> list ;
public RemoveFirstElementThread(ArrayList<String> l) {
list = l ;
}
#Override
public void run() {
while(true){
if(list.isEmpty()){
try{
list.get(0) ;
System.out.println("Hence Proved, that ArrayList is not Thread-safe.");
System.exit(1) ;
}catch (Exception e) {
//continue, if no value is there at index 0
}
}
}
}
}
But, the program never terminates, thus fails to prove thread-safety of ArrayList.
Please, suggest correct implementation to test Thread-safe behaviour of ArrayList and Vector.
Thanks & Best Regards,
Rits
ArrayList is not thread-safe; Vector is. You can wrap an ArrayList with Collections.synchronizedList() if you require it.
The point about unsafe code is there is no guarantee how it will behave when multiple thread are used. You cannot guarantee unsafe code will fail. This is because code is not written to be unsafe, it may not have any guarantees that it is. Thread safety can only be determined by reading and understanding the code.
The problem with thread safety is that it is very hard to prove experimentally. Its not easy to prove something is not thread safe unless you know the exact edge case which will trigger an issue. Additionally, thread safety issues are more or less likely to show depending on the architecture of your system and the load on it. i.e. it can work fine for days and fail unpredictably.
"Thread-safety" on Collections was a pretty bad idea to start with for the vast majority of cases, because it's way too narrow and you need some higher level synchronization anyhow.
In case you really want to remove the first element or add an element to a list, you are better off with for example this here, but your contrived example may need some higher synchronization anyhow (depends on what exactly the semantics should be - if you don't see why, it's probably a really good idea to read something about concurrency)
And finally just have a look at the concurrent framework.