例子题目:

创建10个线程,每个线程执行10000次加1,输出总和

正常结果100000  但是如果出现线程不安全会低于100000

import java.util.concurrent.CountDownLatch;

/**
 * 解决多线程并发遇到的问题 例如:线程安全 主线程等待子线程处理完在执行
 *
 * @author wangbing
 * @since 17 七月 2018
 */
public class TreadSafe {

    //原子操作类
    //static volatile AtomicInteger count = new AtomicInteger(0);
    static int count = 0;
    static Object common = new Object();
    //定义CountDownLatch
    static CountDownLatch countDownLatch = new CountDownLatch(10);

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

        Task task = new Task();//这句代码位置很重要 这是实例一次
        // 下面创建10个线程 参数为同一个实例即上面,因同一个实例(即多个线程共享一个锁)
        // 所以在实例的run上加synchronized可以保证线程安全
        for (int i = 0; i < 10; i++) {
            //Task task = new Task(); //若实例位置在这里,那么每次创建新实例并传入到新线程中,
            //导致10个线程的参数并非同一实例而是10个不同的实例,那么实例run上加synchronized就无效了,
            //因为锁绑定了10个线程,共10个锁,并没有共享一个锁。 但若想实现同步可以锁住一个共享对象如run中注释掉部分
            Thread thread = new Thread(task);
            thread.start();

        }
        countDownLatch.await();
        System.out.println(" 等待子线程结束结果为: " + count);

    }

    static class Task implements Runnable {
        @Override
        public synchronized void run() {

            for (int i = 0; i < 10000; i++) {
                // count.addAndGet(1); //原子加1
                /*synchronized (common) {
                    count++;  //锁住common即锁住多个线程共享唯一的对象,这就可以实现线程安全,解决上面实例位置的不同导致锁错对象
                }*/
                count++;
            }
            countDownLatch.countDown();
        }
    }
}

注释上面写了 解决方案!!

posted on 2018-07-17 20:16  菜霸  阅读(456)  评论(0编辑  收藏  举报