以下代码线程是否安全?

时间:2015-03-04 16:58:38

标签: java concurrency

我在Java Concurrency in Practice一书中看到了以下示例,并且提到该类是线程安全的,并且没有给出有关Person类的信息。如果person类是可变的,那么在添加Person对象之后,它可以被修改,比如说equals方法中使用的值可能被另一个线程修改,在这种情况下,下面的代码将不是线程安全的。这是正确的陈述吗?

@ThreadSafe
public class PersonSet {
@GuardedBy("this")
private final Set<Person> mySet = new HashSet<Person>();

public synchronized void addPerson(Person p) {
    mySet.add(p);
}

public synchronized boolean containsPerson(Person p) {
    return mySet.contains(p);
}

}

4 个答案:

答案 0 :(得分:3)

是的,它是线程安全的。线程安全,因为一次只有一个线程可以通过containsPerson方法读取集合,或者可以通过addPerson方法添加集合。

这个类是线程安全的,因为它有一个Object状态,即Set it self。因此它只允许一个线程处理它来保护它的状态。

但是它不能保证Person不能被多个线程修改。如果你想要实现相同的目标,你可以创建Person作为不可变对象,或者你也使它成为线程安全,即只允许一个线程修改它的状态。

答案 1 :(得分:3)

您的陈述是正确的:如果Person类是可变的,并且对有助于hashCodeequals的字段进行了更新,那么PersonSet将会有问题 - 无论在哪个线程。

没有重复的 Set合同将被打破,无声......

答案 2 :(得分:0)

这里正在使用对象锁(this)。用于访问personSet类的personSet类的方法的对象,没有两个线程可以一次访问personSet的任何方法。在锁定中,没有Person类的依赖。所以personSet类是线程安全的。

答案 3 :(得分:0)

此处讨论的线程安全仅适用于集合,而不属于集合的内容。对集合上的检索(即get)操作没有任何限制或检查,因此该部分是线程不安全的。由于没有公开,所以添加和检查以查看集合中是否包含元素的操作确实是线程安全的。

请注意,虽然这些操作对于线程确实是安全的,但它们也不是并发的。由于synchronized将阻止多个线程同时与该方法交互,因此如果在高度并发的环境中使用,这些方法将成为瓶颈。