JAVA 多线程编程之一(基础)

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

  原子状态,变化不会被打断,如 AtomicLong , AtomicInteger 

2.内部锁  synchronized 块

  synchronized方法的锁就是方法所在的对象本身,可重入

3.共享变量

  Volatile变量,每次从内存取出数据,可以获得最新的副本。

  没有同步情况下的共享变量,可能执行顺序不是按照代码的组织,

  

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

  栈限制,把本地的引用类型限制在本地线程中,不溢出

  不可变对象永远是线程安全的

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

 

 

posted @ 2013-09-05 18:02  张兰云  阅读(410)  评论(0编辑  收藏  举报