【Java多线程】共享变量&同步-异步容器&线程局部变量

共享变量 (Volatile Atomic)

volatile:当多个线程访问一个成员变量的时候,需要这个变量在多个线程中可见

Atomic:Atomic方法对该变量的操作是原子性操作,颗粒度是到对这个变量的一次操作。

private static  AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet();

Atomic+synchronized :如果要保证多线程之间的原子性操作,也就是对一个变量进行多次Atomic方法操纵操作。那就需要加synchronized ,来 保证多线程间的原子性。

private static  AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet();
count.incrementAndGet();
count.incrementAndGet();
//多线程间他们不是原子性操作,如果需要原子性操作,需要在外层方法加synchronized

Volatile

原理:当线程操作该变量的时候会强制去主内存(堆)中去读取。使用方法如下

public class RunThread extends Thread{
    private volatile boolean isRunning = true;

    private void setRunning(boolean isRunning){
        this.isRunning = isRunning;
    }

    public void run(){
        System.out.println("进入run方法..");
        int i = 0;
        while(isRunning == true){
            //..
        }
        System.out.println("线程停止");
    }

    public static void main(String[] args) throws InterruptedException {
        RunThread rt = new RunThread();
        rt.start();
        Thread.sleep(1000);
        rt.setRunning(false);
        System.out.println("isRunning的值已经被设置了false");
    }
}

volatile 变量本身不具备原子性。说明

public class VolatileNoAtomic extends Thread{
    private static volatile int count;
    private static void addCount(){
        for (int i = 0; i < 1000; i++) {
            //count++ ;
            count.incrementAndGet();
        }
        System.out.println(count);
    }

    public void run(){
        addCount();
    }

    public static void main(String[] args) {

        VolatileNoAtomic[] arr = new VolatileNoAtomic[100];
        for (int i = 0; i < 10; i++) {
            arr[i] = new VolatileNoAtomic();
        }

        for (int i = 0; i < 10; i++) {
            arr[i].start();
        }
    }

Atomic

如果要实现原子性(同步),可以使用Atomic类型的变量。如AtomicInteger、AtomicLong…

private static AtomicInteger count = new AtomicInteger(0);

但是,只能保证方法的原子性,不能保证多线程间的原子性。解决方法可以给方法synchronized 修饰,加说明

private static AtomicInteger count = new AtomicInteger(0);

    //多个addAndGet在一个方法内是非原子性的,需要加synchronized进行修饰,保证4个addAndGet整体原子性
    /**synchronized*/
    public synchronized int multiAdd(){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            count.addAndGet(1);
            count.addAndGet(2);
            count.addAndGet(3);
            count.addAndGet(4); //+10
            return count.get();
    }


    public static void main(String[] args) {

        final AtomicUse au = new AtomicUse();

        List<Thread> ts = new ArrayList<Thread>();
        for (int i = 0; i < 100; i++) {
            ts.add(new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(au.multiAdd());
                }
            }));
        }

        for(Thread t : ts){
            t.start();
        }

ThreadLocal

当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。用ThreadLocal可以一定程度减少锁竞争。使用方式如下

public class ConnThreadLocal {

    public static ThreadLocal<String> th = new ThreadLocal<String>();

    public void setTh(String value){
        th.set(value);
    }
    public void getTh(){
        System.out.println(Thread.currentThread().getName() + ":" + this.th.get());
    }

    public static void main(String[] args) throws InterruptedException {

        final ConnThreadLocal ct = new ConnThreadLocal();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                ct.setTh("张三");
                ct.getTh();
            }
        }, "t1");

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                    ct.getTh();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "t2");

        t1.start();
        t2.start();
    }

}
posted @ 2017-04-23 14:01  keivnyau  阅读(467)  评论(0编辑  收藏  举报