如何避免在Java中创建Thread恶意类

Arg*_*dhu 3 java multithreading thread-safety

在有效的Java第2版第70项中,Josh Bloch解释了线程敌对

即使所有方法调用都被外部同步包围,此类对于并发使用也是不安全的.线程敌意通常是在没有同步的情况下修改静态数据

有人可以通过示例向我解释如果类在没有内部同步的情况下修改共享静态数据,那么通过外部同步实现线程安全是不可能的吗?

Tag*_*eev 6

引用假设在同一对象实例上对类方法的每次调用都是同步的.例如,请考虑以下类:

public class Test {
    private Set<String> set = new TreeSet<>();

    public void add(String s) {
        set.add(s);
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然它不是线程安全的,但您可以通过add这种方式安全地调用该方法:

public void safeAdd(Test t, String s) {
    synchronized(t) {
        t.add(s);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果safeAdd从具有相同线程的多个线程调用t,它们将是互斥的.如果使用了不同t的,那么随着独立对象的更新,它也会很好.

但是请考虑我们声明set为静态:

private static Set<String> set = new TreeSet<>();
Run Code Online (Sandbox Code Playgroud)

这样,甚至不同的Test对象也可以访问共享集合.因此,在这种情况下,Test实例上的同步将无济于事,因为set可能仍然会从不同的Test实例同时修改它们,这可能导致数据丢失,随机异常,无限循环或其他任何情况.所以这样的课程将是线程敌对的.