简体   繁体   English

是否包含java.util.List线程安全的方法?

[英]is contains method of java.util.List threadsafe?

I have java.util.List declared as follows: 我有java.util.List声明如下:

private static List<String> extensions = null;

It is populated by single thread always. 它总是由单线程填充。

But multiple threads can call simultaneously method contains(E e) on extensions . 但是多个线程可以同时在extensions上调用contains(E e)方法。

Is it threadsafe ? 它是线程安全的吗?

List is populated by single thread at startup and cannot be modified afterwards. 列表在启动时由单线程填充,之后无法修改。 Is now contains threadsafe? 现在是否包含线程安全?

If you're talking about an ArrayList<T> , as the tags suggest, then yes. 如果您正在谈论ArrayList<T> ,如标签所示,那么可以。 It doesn't make sense to talk about the thread-safety of List<T> , because interfaces have no implementation. 谈论List<T>的线程安全性没有意义,因为接口没有实现。

Looking at arraylist's implementation ( here ), you can see it only reads shared-state, but it doesn't write anything. 查看arraylist的实现( 在此处 ),您可以看到它仅读取共享状态,但不写入任何内容。

Careful though: 不过要小心:

  1. Your field is of type List<T> . 您的字段的类型为List<T> Can you guarantee that the runtime type of the variable stored on that field will always be ArrayList<T> ? 您是否可以保证存储在该字段上的变量的运行时类型始终为ArrayList<T>
  2. The more important question is: does the documentation say the method is thread-safe? 更为重要的问题是:文档是否该方法是线程安全的? If it doesn't, a future release of Java might make it tread- unsafe , which won't be considered a breaking change. 如果不是这样,那么将来的Java版本可能会使它不安全 ,这不会被认为是重大的更改。

If one of your threads was inserting data while the other were calling Contains , then that wouldn't be thread-safe. 如果您的一个线程正在插入数据而另一个线程正在调用Contains ,那么那将不是线程安全的。 Consider add 's implementation: 考虑add的实现:

public void add(int index, E element) {
     rangeCheckForAdd(index);

     ensureCapacity(size+1);  // Increments modCount!!
     System.arraycopy(elementData, index, elementData, index + 1,
                      size - index);
     elementData[index] = element;
     size++;
}

Say you have a list with 4 elements, and its internal array has capacity for 6. The internal array would look like this {a, b, c, d, null, null} and the private field size would be set to 4, to delimit the list's boundaries. 假设您有一个包含4个元素的列表,并且其内部数组可以容纳6个元素。内部数组如下所示: {a, b, c, d, null, null} ,并且私有字段的size将设置为4,以划定列表的边界。

If I now insert x at position 2, here's what'll happen: 如果现在在位置2插入x ,则将发生以下情况:

  1. arraycopy will shift c and d to the right, like so {a, b, c, c, d, null} arraycopy会将cd向右移动,就像{a, b, c, c, d, null}
  2. the next line will insert x , {a, b, x, c, d, null} 下一行将插入x{a, b, x, c, d, null}
  3. The next line will increase size to 5, updating the list's boundaries. 下一行会将size增加到5,从而更新列表的边界。

Notice how, if you called Contains(d) on the list between steps 1 and 3, false would be returned. 请注意,如果您在步骤1和3之间的列表上调用了Contains(d) ,将如何返回false That's because size is still set to 4, and the list appears as if it contained {a,b,c,c} , and {d,null} would be ignored. 这是因为size仍设置为4,并且列表看起来好像包含{a,b,c,c} ,并且{d,null}将被忽略。

List is populated by single thread at startup and cannot be modified afterwards. 列表在启动时由单线程填充,之后无法修改。 Is now contains threadsafe? 现在是否包含线程安全?

An object used in that way is called "effectively immutable"---the program is allowed to change the object, but it doesn't. 以这种方式使用的对象称为“有效不变”- 允许程序更改对象,但不允许更改。 The book, Java Concurrency in Practice by Brian Goetz has a section that deals specifically with safe publication of effectively immutable objects . Brian Goetz撰写的《 Java Concurrency in Practice 》一书专门论述了有效地发布不变对象的安全问题 http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601 http://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601

The short answer (assuming that I am remembering it correctly) is that if you populate the list inside a constructor, and if no other thread can access the list before the constructor returns, then the list is safely published. 简短的答案(假设我没有记错)是,如果将列表填充到构造函数中,并且如果在构造函数返回之前没有其他线程可以访问该列表,则该列表将被安全发布。 I am assuming, of course, that the items you put in the list are also effectively immutable. 我假设,当然,前提是你把列表中的项目也有效不变。

"Safe publication" means that other threads will be guaranteed to see the list in its intended, final state. “安全发布”意味着可以保证其他线程可以以预期的最终状态查看列表。 If the list were not safely published, then threads running on different processors could see different versions of the list (potentially including some version where the list was in an inconsistent state that could crash your program when you tried to access it.) 如果该列表未安全发布,则在不同处理器上运行的线程可能会看到该列表的不同版本(可能包括某些列表处于不一致状态的版本,当您尝试访问该列表时,它们可能会导致程序崩溃。)

No, List is not Thread safe by default. 不,默认情况下,列表不是线程安全的。 If you want to make it thread safe . 如果要使其线程安全。 Use Collections.synchronizedList(). 使用Collections.synchronizedList().

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM