简体   繁体   中英

Simple question on java synchronization

I would like to iterate over a java List using the old fashion for(int i...) loop, since for a given i and loop iteration, I want to access several elements relative to i. Then I can't use for(Object o: objects) neither the list iterator.

How can I ensure that no other code can access the list while I'm executing it?

I tried

synchronized(path.getPoints()){
    for (int i = 0; i < path.getPoints().size(); i++){
        ...
    }
}

where path is the object holding the list, and also

synchronized(path){
    for (int i = 0; i < path.getPoints().size(); i++){
        ...
    }
}

and also

synchronized(this){
    for (int i = 0; i < path.getPoints().size(); i++){
        ...
    }
}

where "this" is the renderer that would like to render the path quitely without synchronization issue.

Thanks in advance,

Martin

How can I ensure that no other code can access the list while I'm executing it?

By making sure that all other code also synchronizes on the same object. synchronized(path.getPoints()) is the best choice. It might be a good idea for getPoints() to return the list wrapped via Collections.synchronizedList() - then you don't need to synchronize simple get() or add() calls explicitly, but you still need the synchronization for the iteration.

Complicated? Yeah. That's why shared-memory multithreaded programming is considered very difficult.

You can avoid synchronization completely by using a copy on write approach. It has an associated cost but that may be acceptable to you: http://download.oracle.com/javase/6/docs/api/java/util/concurrent/CopyOnWriteArrayList.html

You could make path.getPoints() synchronized and return a copy of the points list (or maybe an array). Then you don't need to sync while iterating over it. If points is private you can easily make sure that all the methods in Path that access it are also synchronized.

"synchronized (this)" (where "this" is your renderer) makes sure that no other thread can run the same renderer at the same time; other threads can, however, access the list and the "path" object.

你最好的做法可能是确保使用集合( path.getPoints() )进行写入的任何事情都是在同步块(在同一个集合中)这样做,以便消费者(例如只读)想要在其上使用枚举器的集合也可以通过在集合上使用synchronized块来安全地执行此操作。

I would suggest you write this as.

List<Point> points = path.getPoints()
synchronized(points){
    for (Point point: points){
        ...
    }
}

This ensure getPoints() doesn't return something different and simplifies the code IMHO.

I would also use @Michaels suggestion of either synchronizing every time the getPoints() is accessed or make it a Collectons.synchronizedList() or a thread safe list like CopyOnWriteArrayList()

Note: if you use a thread safe list, you may not need to synchronize it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM