美文网首页
并发编程(4)

并发编程(4)

作者: 禾叶super | 来源:发表于2019-11-29 17:34 被阅读0次

上一篇文章提到了并发编程中常见的问题,饥饿、死锁以及竞争条件。本文就尝试解决这些问题。每一种解决问题的方法都有其适用的场景,在使用方法之前,我们需要了解其适用场景。

public class Test {
    private static int count = 0; // 共享变量
    private static CountDownLatch latch = new CountDownLatch(100);

    /*public static int getCount(final int scale) {
        count += scale;
        return count;
    }

    public static void setCount(int count) {
        Test.count = count;
    }*/

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        try {
            for (int i = 1; i <= 100; i++) {
                final int scale = i;
                executorService.submit(new Runnable() {
                    @Override
                    public void run() {
                        //getCount(scale);
                        synchronized (Test.class) {
                            count += scale;
                        }
                        try {
                            TimeUnit.SECONDS.sleep(1); // 模拟线程执行的长时任务
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        latch.countDown();
                    }
                });
            } // end for
        }finally {
            executorService.shutdown();
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(count);
    }
}

上述的实例中,count是一个共享变量,即每一个线程都可以更改count的值,而且在同一时刻可能会有多个线程同时更改count值,共享可变性会造成同步问题,使结果不准确。上述实例模拟了计算1-100之和,开启了100个线程,最终的结果应为:5050。

在没有加synchronized 同步块时,结果如下:


image.png

每次的结果都不一定相同。这就是竞争条件带来的问题。
解决方法一:使用synchronized关键字来显示地获取对象的monitor/锁。 锁机制实现同步。同一时刻最多只有一个线程执行加synchronized 的代码。
解决方法二:使用java.util.concurrent.atomic包中定义的原子操作类。原子操作类对于处理单个共享数据的值来说非常有用。如下实例2

实例2

public class Test {
    private static AtomicInteger count = new AtomicInteger(0); // 共享变量
    private static CountDownLatch latch = new CountDownLatch(100);

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        try {
            for (int i = 1; i <= 100; i++) {
                final int scale = i;
                executorService.submit(new Runnable() {
                    @Override
                    public void run() {
                        count.addAndGet(scale);
                        try {
                            TimeUnit.SECONDS.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        latch.countDown();
                    }
                });
            } // end for
        }finally {
            executorService.shutdown();
        }
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(count.get());
    }
}

相关文章

网友评论

      本文标题:并发编程(4)

      本文链接:https://www.haomeiwen.com/subject/nmpgwctx.html