同步块是否会阻止其他线程访问对象?

发布于 2024-10-01 20:05:03 字数 278 浏览 4 评论 0原文

如果我对同步块内的列表执行某些操作,是否会阻止其他线程在其他地方访问该列表?

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

自我难过 2024-10-08 20:05:03

不,事实并非如此。

synchronized 块仅阻止其他线程进入该块(更准确地说,它阻止其他线程进入在同一对象实例上同步的所有块 - 在本例中为在 this)。

您需要在 synchronized 块中使用要保护的实例:

synchronized(myList) {
  mylist.add("Hello");
}

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 on this).

You need to use the instance you want to protect in the synchronized block:

synchronized(myList) {
  mylist.add("Hello");
}

The whole area is quite well explained in the Java tutorial:

http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

空城缀染半城烟沙 2024-10-08 20:05:03

是的,但仅当对 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., using synchronized (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).

浮生面具三千个 2024-10-08 20:05:03

这里 sychronized 确保一次只有一个线程将 Hello 添加到 myList...

要更具体地了解同步 wrt 对象,您可以使用

synchronized( myList ) //object name
{
    //other code
}

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

synchronized( myList ) //object name
{
    //other code
}

vinod

飘然心甜 2024-10-08 20:05:03

根据我对 Java 并发控制的有限理解,我想说上面的代码不太可能呈现您正在寻找的行为。

同步块将使用您在其中调用所述代码的任何对象的锁,这绝不会阻止任何其他代码访问该列表,除非所述其他代码也使用相同的锁对象进行同步。

我不知道这是否有效,或者是否有任何建议,但我认为:

List myList = new ArrayList();

同步(myList){ mylist.add("你好"); }

通过同步列表本身的锁定对象,将给出您所描述的行为。

然而,Java文档推荐使用这种方式来获取同步列表:

List list = Collections.synchronizedList(new ArrayList(...));

请参阅: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:

List myList = new ArrayList();

synchronized(myList) { mylist.add("Hello"); }

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:

List list = Collections.synchronizedList(new ArrayList(...));

See: http://download.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文