Java并发编程实战-学习总结-第一篇(概括)

看《Java并发编程实战》有一段时间了,决定将看书学习的过程记录下来,
以方便以后查阅及完善,文章中会记录一些书上的知识,同时也会记录一下
自己的理解,如有不对的地方希望看到的小伙伴给与指正谢谢!微笑。

提到并发编程,肯定是与线程分不开的。本系列文章将讨论并发编程中
的多线程,而不讨论多进程的知识。

基于java的应用程序并发无处不在。我们最熟悉的使用的最多的web容器
Tomcat就是多线程的容器,它为每个用户请求都开一个线程来处理(这里的开
线程不一定是new一个线程,因为tomcat是基于线程池的)。所以这就是为什
么经常有面试官会问struts1是线程安全的吧,struts2是线程安全的吗?为
什么?

提到线程,我觉得一个最应该知道或是最应该充分理解的一个问题是线程
安全性问题。这也是《Java并发编程实战》为什么把线程安全性放在第一部分
基础知识里第一章的原因。我们平时在开发时,单线程的程序都会有bug,到
了并发多线程的时候bug不但不会少,而且出现的bug经常是不知道是什么原
因造成的。当我们了解了线程的安全性问题及其本质,这样再开发多线程程
序,才能够尽量的减少关于并发所产生的bug问题。在安全性问题里,提到的
最多的就是可见性和原子性。如果你的程序能够保证原子性,那么肯定保证了
可见性,但如果你的程序保证了可见性,不一定能够保证原子性。具体的可见
性和原子性问题将会在后续的文章中细化记录。

为什么线程会出现不安全的情况?那是因为线程章通信问题。线程章通信
可以有多种方式,最直接的方式就是共享对象。java中的线程间通信就是采用
共享对象的机制。因为对象是共享的,就可能会出现多个线程并发的修改共享
的对象,这样就会造成不一致情况,例如如下程序(如果你幸运的话,你会得
到10000,但是如果运行多次你一定不会是每次都能得到进10000)。这就是线
程不安全性的问题。

public class UnsafeSequence {

    private static int count = 0;

    public static void main(String[] args) {
        List<Thread> list = new ArrayList<Thread>();
        for (int i = 0; i < 10000; i++) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    countSequence();
                }
            });
            t.start();
            list.add(t);
        }
        try {
            for (Thread t : list) {
                t.join();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(count);
    }

    public static int countSequence() {
        try {
            // 模拟程序耗时
            long l = new Random().nextInt(9) * 10;
            Thread.sleep(l);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return count++;
    }
}

怎么解决它?有很多方式,最简单直接的方法就是用synchronized关键字,代码修改如下:

public class UnsafeSequence {

    private static int count = 0;

    public static void main(String[] args) {
        List<Thread> list = new ArrayList<Thread>();
        for (int i = 0; i < 10000; i++) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    countSequence();
                }
            });
            t.start();
            list.add(t);
        }
        try {
            for (Thread t : list) {
                t.join();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(count);
    }

    public static int countSequence() {
        try {
            // 模拟程序耗时
            long l = new Random().nextInt(9) * 10;
            Thread.sleep(l);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        /////////这里用了synchronized 关键字,就是这么简单,既保证了可见性又保证了原子性。
        synchronized (UnsafeSequence.class) {
            return count++;
        }
    }
}

上面的例子只是简单的示意了一下并发编程的安全性问题以及简单的解决方案。
第一次写博客,先写这么多吧。文采不好,以后继续努力。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值