关于java同步的简单问题

时间:2011-03-31 09:42:18

标签: java synchronization

我想使用旧方式(int i ...)循环遍历java List,因为对于给定的i和循环迭代,我想访问相对于i的几个元素。然后我不能使用(对象o:对象)列表迭代器。

如何在执行时确保没有其他代码可以访问列表?

我试过

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

其中path是保存列表的对象,也是

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

以及

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

其中“this”是想要在没有同步问题的情况下完全呈现路径的渲染器。

提前致谢,

马丁

6 个答案:

答案 0 :(得分:7)

  

如何确保没有其他代码   我可以访问列表   执行它?

确保所有其他代码在同一对象上同步。 synchronized(path.getPoints())是最佳选择。 getPoints()返回通过Collections.synchronizedList()包装的列表可能是一个好主意 - 然后您不需要明确同步简单的get()add()调用,但您仍然需要迭代的同步。

复杂?是啊。这就是共享内存多线程编程被认为非常困难的原因。

答案 1 :(得分:1)

您可以通过使用写入方法的副本完全避免同步。它有相关的费用,但您可以接受:http://download.oracle.com/javase/6/docs/api/java/util/concurrent/CopyOnWriteArrayList.html

答案 2 :(得分:0)

您可以使path.getPoints()同步并返回点列表的副本(或者可能是数组)。然后,在迭代它时不需要同步。如果point是私有的,您可以轻松确保Path中访问它的所有方法也是同步的。

答案 3 :(得分:0)

“synchronized(this)”(其中“this”是您的渲染器)确保没有其他线程可以同时运行相同的渲染器;但是,其他线程可以访问列表和“路径”对象。

答案 4 :(得分:0)

最好的做法可能是确保使用集合(path.getPoints())进行写入的任何内容都是在同步块(在同一个集合中)上进行,以便消费者(例如,阅读 - 只有那个想要在其上使用枚举器的集合才能安全地使用集合上的同步块。

答案 5 :(得分:0)

我建议你把它写成。

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

这确保getPoints()不会返回不同的东西并简化代码恕我直言。

我还会使用@Michaels建议每次访问getPoints()时进行同步,或者将其设置为Collectons.synchronizedList()或类似线程安全列表 的CopyOnWriteArrayList()

注意:如果您使用线程安全列表,则可能不需要同步它。