例子题目:
创建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(); } } }
注释上面写了 解决方案!!