并发案例(二)

1.非线程安全
    main线程更新ready址 , ReaderThread 线程持续检测ready状态 ,直到ready为true.
    正常来讲,程序会输出42 ;但也有可能输出0 , 甚至可能程序复发终止。
        输出0: 
 
@NotSafeThread
 
 
 
 
public class NoVisibility {
    private static boolean ready;
    private static int number;
 
 
    private static class ReaderThread extends Thread {
        public void run() {
 
            while (!ready)
                Thread.yield();
 
            System.out.println(number);
        }
 
    }
 
    public static void main(String[] args) {
        new ReaderThread().start();
        number = 42;
        ready = true;
 
    }
 }
 
 
 
 
 
 
@NotThreadSafe
public class MutableInteger {
 
    private int value;
 
    public int  get() { return value; }
 
    public void set(int value) { this.value = value; }
}
 
 
 
 
 
 
 
 
 
 
 
 
@ThreadSafe
public class SynchronizedInteger {
 
    @GuardedBy("this") private int value;
 
    public synchronized int get() { return value; }
 
    public synchronized void set(int value) { this.value = value; }
}
 
 
 
 
@NotThreadSafe
 
 
 
 
class UnsafeStates {
    private String[] states = new String[] {
 
        "AK", "AL" ...
    };
 
    public String[] getStates() { return states; }
}
 
 
 
 
 
 
@NotSafeThread
 
 
 
 
 
 
 
 
 
public class ThisEscape {
    public ThisEscape(EventSource source) {
 
 
 
 
 
 
 
 
 
 
source.registerListener(
    new EventListener() {
 
        public void onEvent(Event e) {
            doSomething(e);
 
} });
 
 
 
 
} }
 
 
 
 
 
 
 
 
 
临时阻塞 
    这个技术尽量少用,比较脆弱。应当使用更加健壮的 栈阻塞 或者是 ThreadLocal
@SafeThread
 
 
 
 
public class SafeListener {
    private final EventListener listener;
 
    private SafeListener() {
        listener = new EventListener() {
 
            public void onEvent(Event e) {
                doSomething(e);
 
} };
 
}
 
    public static SafeListener newInstance(EventSource source) {
        SafeListener safe = new SafeListener();
        source.registerListener(safe.listener);
        return safe;
 
} }
 
 
 
 
栈阻塞 
    通过 局部变量(local variables) —— 本例中是局部的原始变量, 运行在线程的栈上 ,不会和别的线程共享,来保证线程安全。
 
 
 
 
 
public int loadTheArk(Collection<Animal> candidates) {
    SortedSet<Animal> animals;
    int numPairs = 0;
    Animal candidate = null;
 
    // animals confined to method, don't let them escape!
    animals = new TreeSet<Animal>(new SpeciesGenderComparator());
    animals.addAll(candidates);
    for (Animal a : animals) {
 
        if (candidate == null || !candidate.isPotentialMate(a))
            candidate = a;
 
        else {
            ark.load(new AnimalPair(candidate, a));
            ++numPairs;
            candidate = null;
 
} }
 
    return numPairs;
}
 
 
 
 
 
 
利用ThreadLocal保证线程安全
以jdbc connection 为例,每个线程一个connection 。
 
 
 
 
private static ThreadLocal<Connection> connectionHolder
    = new ThreadLocal<Connection>() {
 
        public Connection initialValue() {
            return DriverManager.getConnection(DB_URL);
 
} };
 
public static Connection getConnection() {
    return connectionHolder.get();
 
}
 
 
 
 
 
 
 
 
@Immutable
public 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);
 
} }
 
 
posted @ 2019-07-04 13:36  豆豆飞  阅读(151)  评论(0编辑  收藏  举报