1

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

这是否意味着:如果我在一个线程中创建一个对象并将其放入 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);

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

在另一个线程中

......

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;

  }

}
4

4 回答 4

1
  1. 所有线程都可以看到它们可以引用的所有对象,所以是的,这也适用于集合。并发集合使用同步不会中断,因为两个或多个线程同时访问它们(例如,for-loop 可以中断),因此您可以使用它们在线程之间共享对象。

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

同步的重点是确保您的变量在 n 次操作中保持一致。例子:

如果你想计算

i = i + 2;

然后这包括首先读取 i 的值,加 2,然后将值设置回 i。

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

于 2011-03-23T15:30:33.337 回答
0

JSR 133还指定Object的final字段是完整的,并且在构造函数完成时对所有线程可见。Java 5.0(2004 年)中添加了此支持。您的对象无需其他操作即可在所有线程中可见且正确。

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

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

于 2011-03-23T15:08:30.070 回答
0

确切地。在这种情况下ConcurrentLinkedQueue,作为同步器工作。

于 2011-03-23T15:22:57.697 回答
0

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

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

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

于 2011-03-23T15:23:23.737 回答