java.util.concurrent 中的内存一致性

发布于 2024-10-25 22:47:16 字数 1566 浏览 1 评论 0原文

来自内存一致性属性,我们知道: “将对象放入任何并发集合之前的线程中的操作发生在另一个线程中从集合中访问或删除该元素之后的操作之前。”

这是否意味着:如果我创建一个对象并将其放入一个线程中的 ConcurrentLinkedQueue 中,另一个线程将看到该对象的所有属性,而无需对该对象进行其他同步?

例如:

public class Complex{

  int index;

  String name;

  public Complex(int index, String name){

     this.index = index;

     this.name = name;

  }

  public String getName(){

     return name;

  }

  public int getIndex(){

     return index;

  }

}

public class SharedQueue{

   public static ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();

}

在一个线程中:

........................................

Complex complex = new Complex(12, "Sam");

SharedQueue.queue.add(complex);

在另一个线程中< /strong>

......

Complex complex = SharedQueue.queue.poll();

System.out.printly(complex.getIndex() + ";" + complex.getName());

......

第二个线程一定会看到complex对象的属性吗?如果在第一个线程将对象放入队列后,第二个线程恰好获取该对象并打印它。

我们知道,在正常情况下,如果是共享的,我们应该在多线程环境中同步对象。

喜欢

public class Complex{

  int index;

  String name;

  public Complex(int index, String name){

     this.index = index;

     this.name = name;

  }

  public synchronized String getName(){

     return name;

  }

  public synchronized int getIndex(){

     return index;

  }

}

From Memory Consistancy Property, we know that:
"Actions in a thread prior to placing an object into any concurrent collection happen-before actions subsequent to the access or removal of that element from the collection in another thread."

Does this means: if I create an object and put it into ConcurrentLinkedQueue in one thread, another thread will see all properties of the object without other synchronization on the object?

For example:

public class Complex{

  int index;

  String name;

  public Complex(int index, String name){

     this.index = index;

     this.name = name;

  }

  public String getName(){

     return name;

  }

  public int getIndex(){

     return index;

  }

}

public class SharedQueue{

   public static ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue();

}

in one thread:

...........

Complex complex = new Complex(12, "Sam");

SharedQueue.queue.add(complex);

...........

in another thread

......

Complex complex = SharedQueue.queue.poll();

System.out.printly(complex.getIndex() + ";" + complex.getName());

.............

Does the second thread will surely see the properties of complex object? if the second thread happens to fetch the object and print it after the first thread put the object to the queue.

We know that in normal case we should synchronize the object in multiple-threads environments if it's share.

Like

public class Complex{

  int index;

  String name;

  public Complex(int index, String name){

     this.index = index;

     this.name = name;

  }

  public synchronized String getName(){

     return name;

  }

  public synchronized int getIndex(){

     return index;

  }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(4

北音执念 2024-11-01 22:47:16
  1. 所有线程都会看到它们可以获得引用的所有对象,所以是的,这也适用于集合。并发集合使用同步来避免两个或多个线程同时访问它们时中断(例如,for 循环可能中断),因此您可以使用它们在线程之间共享对象。

  2. 如果您的对象是不可变的,即只读,如上面的 Complex 类(添加最终修饰符),那么您不需要同步对其的访问,因为它是线程安全的。

同步的目的是确保变量在 n 次操作中保持一致。示例:

如果要计算

i = i + 2;

,则需要首先读取 i 的值,加 2,然后将值设置回 i。

现在,如果在您添加 2 之后某个其他线程出现并更新 i,那么您实际上会覆盖此更新,因为您仍然保留基于先前值 + 2 的总和,并将其设置回 i。

  1. All threads see all objects they can get a reference to, so yes, this also applies to collections. The concurrent collections are using synchronization not to break as two or more threads access them at the same time (for example, for-loop can break), thus you can use them to share objects between threads.

  2. If you object is immutable, i.e. read-only, as your Complex class above (adding final modifiers), then you need not synchronize access to it, as it is thread-safe.

The point of synchronization is to ensure that your variables are consistent over n number of operations. Example:

If you want to compute

i = i + 2;

then this consists of first reading value of i, adding 2, and then setting the value back at i.

Now if some other thread comes and updates i just after you added 2, then you would in effect be overwriting this update as you are still holding the sum based on the previous value + two, setting it back to i.

只为守护你 2024-11-01 22:47:16

确切地。在这种情况下,ConcurrentLinkedQueue 充当同步器。

Exactly. In this case ConcurrentLinkedQueue works as synchronizer.

我不吻晚风 2024-11-01 22:47:16

这意味着,如果线程 A 将一个对象放入集合中,并且线程 B 从那里获取该对象,则线程 B 可以在将对象放入集合之前看到线程 A 执行的任何操作的结果(以及发生的操作)在其他线程中的它们之前,等等)。这些操作包括对象的初始化(如果是由线程 A 完成的),以便线程 B 可以看到处于一致状态的对象。

请注意,它不提供有关将对象放入集合后线程 A 中发生的操作或其他线程的操作的任何保证(除了与传递 happens-before 顺序相关的操作,如上所述) ,因此如果您要在将对象放入集合后修改该对象,您仍然需要同步。

顺便说一句,您的“正常情况”示例已损坏,因为构造函数中的操作不同步。

It means that if thread A places an object into collection, and thread B obtains it from there, thread B can see results of any actions done by thread A before placing the object into collection (as well as the actions that happened-before them in other threads, etc). These actions include initialization of the object (if it was done by thread A), so that thread B can see the object in consistent state.

Note that it doesn't provide any guarantees about actions that happened in thread A after placing object into collection or about actions of other threads (except for actions connected with transitive happens-before order, as noted above), so that you still need synchronization if you are going to modify the object after placing it into collection.

By the way, your "normal case" sample is corrupt, since actions in constructor are not synchronized.

墨小墨 2024-11-01 22:47:16

JSR 133 还指定了当构造函数完成时,对象已完成并对所有线程可见。 Java 5.0(2004 年)中添加了此支持。无需执行任何其他操作即可使您的对象在所有线程中可见且正确。

在这种情况下,在不可变对象上使用同步不会实现任何目标。

有很多文件另有说明,而且这些文件通常早于 2004 年。;)

The JSR 133 also specifies that final fields of an Object is complete and visible to all threads when the constructor completes. This support was added in Java 5.0 (in 2004). No other action is required for your object to be visible and correct in all threads.

Using synchronized on an immutable object doesn't achieve anything in this case.

There are plenty of documents which state otherwise and these generally predate 2004. ;)

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