2011-03-31 112 views
2

我想迭代一个java List,使用旧的方式for(int i ...)循环,因为对于给定的i和循环迭代,我想访问多个相对于i的元素。然后我不能使用(Object o:objects)列表迭代器。关于java同步的简单问题

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

我试图

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

其中路径对象容纳的列表,并且还

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

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

其中 “这” 是想渲染器在没有同步问题的情况下退出路径。

由于提前,

马丁

+0

您发布的同步代码应该适用于所有三种情况。你确定你没有其他线程访问同步守卫之外的路径吗? – templatetypedef 2011-03-31 09:44:39

+0

是什么让你认为另一个线程正在访问列表? – 3urdoch 2011-03-31 09:47:12

+0

@murdoch:我有一个编辑器线程在后台运行,一个UI线程连续运行并呈现点列表。 @template:我只同步这两个线程中的一个,而不是两个 – Martin 2011-04-01 10:31:03

回答

7

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

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

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

+0

我认为在这个特定的问题中,使用synchronizedList是无用的,因为您必须使用同一个同步对象来同步所有获取,添加和迭代。看到我的回答... – nanda 2011-03-31 10:04:25

+0

@nanda:实际上,这种情况被正确描述为正确使用API​​文档中synchronizedList()的示例。显然,包装器使用它自己进行同步,以便允许外部同步工作。 – 2011-03-31 10:12:50

+0

你是对的... – nanda 2011-03-31 10:16:49

0

你可以做path.getPoints()同步,并返回点列表(或者数组)的副本。然后在迭代它时不需要同步。如果点是私密的,你可以很容易地确保Path中访问它的所有方法也是同步的。

0

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

0

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

0

我建议你这样写。

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

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

我也将使用@Michaels的建议,无论是同步每次getPoints()被访问或进行一次一Collectons.synchronizedList()或线程安全的名单像 的CopyOnWriteArrayList()

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