同步块是否会阻止其他线程访问对象?
如果我对同步块内的列表执行某些操作,是否会阻止其他线程在其他地方访问该列表?
List<String> myList = new ArrayList<String>();
synchronized {
mylist.add("Hello");
}
这是否会阻止其他线程迭代 myList
并删除/添加值?
我正在寻找从列表中添加/删除值,但同时保护它免受其他线程/方法的迭代(因为列表中的值可能会无效)
If I do something to a list inside a synchronized block, does it prevent other threads from accessing that list elsewhere?
List<String> myList = new ArrayList<String>();
synchronized {
mylist.add("Hello");
}
Does this prevent other threads from iterating over myList
and removing/adding values?
I'm looking to add/remove values from a list, but at the same time protect it from other threads/methods from iterating over it (as the values in the list might be invalidated)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不,事实并非如此。
synchronized
块仅阻止其他线程进入该块(更准确地说,它阻止其他线程进入在同一对象实例上同步的所有块 - 在本例中为在this
)。您需要在
synchronized
块中使用要保护的实例:Java 教程中对整个区域进行了很好的解释:
http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
No, it does not.
The
synchronized
block only prevents other threads from entering the block (more accurately, it prevents other threads from entering all blocks synchronized on the same object instance - in this case blocks synchronized onthis
).You need to use the instance you want to protect in the
synchronized
block:The whole area is quite well explained in the Java tutorial:
http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
是的,但仅当对
myList
的所有其他访问均受同一对象上的同步块保护时。您发布的代码示例缺少您同步的对象(即您获取其互斥锁的对象)。如果您在不同的对象上进行同步,或者在一个实例中根本无法同步,那么其他线程很可能会同时访问该列表。因此,在访问对象之前,必须确保所有线程都必须在同一对象上进入同步块(例如,一致地使用synchronized (myList) { ... }
)列表。事实上,已经有一个工厂方法可以为您使用同步方法包装列表中的每个方法:Collections.synchronizedList
。但是,您当然可以使用
Collections.synchronizedList
来包装您的列表,以便其所有方法都单独同步,但这并不一定意味着您的应用程序的不变量会得到维护。将列表中的每个方法单独标记为同步将确保列表的内部状态保持一致,但您的应用程序可能希望更多,在这种情况下,您将需要编写一些更复杂的同步逻辑,或者看看是否可以利用 < a href="http://download.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html" rel="nofollow">并发 API (强烈推荐) 。Yes, but only if all other accesses to
myList
are protected by synchronized blocks on the same object. The code sample you posted is missing an object on which you synchronize (i.e., the object whose mutex lock you acquire). If you synchronize on different objects or fail to synchronize at all in one instance, then other threads may very well access the list concurrently. Therefore, you must ensure that all threads have to enter a synchronized block on the same object (e.g., usingsynchronized (myList) { ... }
consistently) before accessing the list. In fact, there is already a factory method that will wrap each method of your list with synchronized methods for you:Collections.synchronizedList
.However, you can certainly use
Collections.synchronizedList
to wrap your list so that all of its methods are individually synchronized, but that doesn't necessarily mean that your application's invariants are maintained. Individually marking each method of the list as synchronized will ensure that the list's internal state remains consistent, but your application may wish for more, in which case you will need to write some more complex synchronization logic or see if you can take advantage of the Concurrency API (highly recommended).这里 sychronized 确保一次只有一个线程将 Hello 添加到 myList...
要更具体地了解同步 wrt 对象,您可以使用
vinod
here the sychronized makes sure that only one thread is adding Hello to the myList at a time...
to be more specific about synchronizing wrt objects yu can use
vinod
根据我对 Java 并发控制的有限理解,我想说上面的代码不太可能呈现您正在寻找的行为。
同步块将使用您在其中调用所述代码的任何对象的锁,这绝不会阻止任何其他代码访问该列表,除非所述其他代码也使用相同的锁对象进行同步。
我不知道这是否有效,或者是否有任何建议,但我认为:
通过同步列表本身的锁定对象,将给出您所描述的行为。
然而,Java文档推荐使用这种方式来获取同步列表:
请参阅:http://download.oracle.com /javase/1.4.2/docs/api/java/util/ArrayList.html
From my limited understanding of concurrency control in Java I would say that it is unlikely that the code above would present the behaviour you are looking for.
The synchronised block would use the lock of whatever object you are calling said code in, which would in no way stop any other code from accessing that list unless said other code was also synchronised using the same lock object.
I have no idea if this would work, or if its in any way advised, but I think that:
would give the behaviour you describe, by synchronizing on the lock object of the list itself.
However, the Java documentation recommends this way to get a synchronized list:
See: http://download.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html