java 并发安全的思考

来源:互联网 发布:论持久战的影响知乎 编辑:程序博客网 时间:2024/05/15 13:09

保证并发安全性的方式有三种:不共享、不可变、同步。

不共享——线程封闭

线程封闭(thread confinement):数据在单线程中进行访问,不需要同步策略。

当某个对象封闭在一个线程中时,这种用法将自动实现线程安全,即使被封闭的对象本身不是线程安全的

Ad-hoc线程封闭

Ad-hoc线程封闭是指,维护线程封闭性的职责完全由程序来实现。没有任何一种语言特性,能够将对象封闭到目标线程上。

在volatile变量上存在一种特殊的线程封闭,只要你确保只有单个线程对共享的volatile变量执行写入操作,那个就可以安全地在这些共享的volatile变量上执行”读取-修改-写入”的操作。

栈封闭

位于执行线程的栈中,其他线程无法访问这个栈。局部变量的固有属性之一就是封闭在执行线程中。

  • 基本类型的局部变量,由于任何方法都无法获得对基本类型的引用,所以不会破坏栈封闭性。
  • 引用类型,必须确保不会发布该引用类型。
public int loadTheArk(Collection<Animal> candidates) {    SortedSet<Animal> animals;    int numPairs = 0;    Animal candidate = null;   //保存对象的引用animals变量被封闭在方法中    animals = new TreeSet<Animal>(new SpeciesGenderComparator());    animals.addAll(candidates);    for(Animal a : animals) {        if (candidates == null || !candidate.isPotentialMate(a))            candidate = a        else{            ark.load(new AnimalPair(candidate, a));            ++numPairs;            candidate = null        }    }    return numPairs;}

ThreadLocal类

通常使用ThreadLocal保证可变的单例变量(Singletion)或全局变量进行共享。

例如,在单线程应用程序中可能会维持一个全局的数据库连接,并在程序启动时初始化这个连接对象,从而避免在调用每个方法时都要传递一个Connection对象。

public int loadTheArk(Collection<Animal> candidates) {    SortedSet<Animal> animals;    int numPairs = 0;    Animal candidate = null;    animals = new TreeSet<Animal>(new SpeciesGenderComparator());    animals.addAll(candidates);    for(Animal a : animals) {        if (candidates == null || !candidate.isPotentialMate(a))            candidate = a        else{            ark.load(new AnimalPair(candidate, a));            ++numPairs;            candidate = null        }    }    return numPairs;}

不可变——不变性

如果某个对象在被创建后其状态就不能被修改,那么这个对象就称为不可变对象。线程安全性是不可变对象的固有属性之一。

满足以下条件,对象才是不可变的:

  • 对象创建以后其状态就不能修改。
  • 对象的所有域都是final类型。
  • 对象在创建期间,this引用没有逸出。
@Immutablespublic final class ThreeStooges {    //在可变对象基础上构建的不可变类    private final Set<String> stooges = new HashSet<String>();    public ThreeStooges() {        stooges.add("Moe");        stooges.add("Larry");        stooges.add("Curly");    }    public boolean isStooge(String name) {        return stooges.contains(name)    }}

同步

同步是指通过同步策略访问共享的变量(锁、信号量等)。

0 0