JAVA 多線程編程之一(基礎)

1.原子變量(java.util.concurrent.atomic)java

  原子狀態,變化不會被打斷,如 AtomicLong , AtomicInteger 緩存

2.內部鎖  synchronized 塊安全

  synchronized方法的鎖就是方法所在的對象自己,可重入多線程

3.共享變量併發

  Volatile變量,每次從內存取出數據,能夠得到最新的副本。高併發

  沒有同步狀況下的共享變量,可能執行順序不是按照代碼的組織,this

  

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;
    }

  棧限制,把本地的引用類型限制在本地線程中,不溢出atom

  不可變對象永遠是線程安全的spa

4.ThreadLocal   容許線程和本身的變量保存在一塊兒線程

  向已有的線程安全類添加功能,

  

public class BetterVector<E> extends Vector<E>{
    public synchronized boolean putIfAbsent(E x){
        ...
    }
}

 

  可是下面這種方式不是線程安全的:

 

public class ListHelper<E>{
    public List<E> list = Collections.synchronizedList(new ArrayList<E>());

    public synchronized boolean putIfAbsent(E x){
               ...
    }
}

由於synchronized關鍵字鎖住的是 ListHelpder類,因此並無得到List的鎖,那麼在putIfAbsent中修改List時,是不能保證

其它方法不對list修改。

下面的方法纔是正確的:

public class ListHelper<E>{
    public List<E> list = Collections.synchronizedList(new ArrayList<E>());

    public  boolean putIfAbsent(E x){
            synchronized(list);
               ...
    }
}

 

或者是使用組合實現List接口,這樣第一種方式就是正確的,由於得到了正確的鎖。

5. 同步容器

   Java 5.0 提供了併發容器來替換同步容器,提升併發的效率。 ConcurrentHashMap代替SynchronizedMap

   FutureTask 經過Callable 實現,能夠理解爲是一個可攜帶結果的Runnable

   semaphore 信號量,控制對資源的訪問數量限制

   Barrier  提供一種能夠一次執行多個線程,直到全部的線程都完成才繼續進行,有任何一個線程沒有完成,全部 

              完成的現成都要等待這個線程完成

 

  一個正確的多線程訪問的緩存的寫法

  

package net.jcip.examples;

import java.util.concurrent.*;

/**
 * Memoizer
 * <p/>
 * Final implementation of Memoizer
 *
 * @author Brian Goetz and Tim Peierls
 */
public class Memoizer <A, V> implements Computable<A, V> {
    private final ConcurrentMap<A, Future<V>> cache
            = new ConcurrentHashMap<A, Future<V>>();
    private final Computable<A, V> c;

    public Memoizer(Computable<A, V> c) {
        this.c = c;
    }

    public V compute(final A arg) throws InterruptedException {
        while (true) {
            Future<V> f = cache.get(arg);
            if (f == null) {
                Callable<V> eval = new Callable<V>() {
                    public V call() throws InterruptedException {
                        return c.compute(arg);
                    }
                };
                FutureTask<V> ft = new FutureTask<V>(eval);
                f = cache.putIfAbsent(arg, ft);
                if (f == null) {
                    f = ft;
                    ft.run();
                }
            }
            try {
                return f.get();
            } catch (CancellationException e) {
                cache.remove(arg, f);
            } catch (ExecutionException e) {
                throw LaunderThrowable.launderThrowable(e.getCause());
            }
        }
    }
}
相關文章
相關標籤/搜索