java并发编程实战(一)简介

java并发编程实战(一)

第Ⅰ章 简介

并发简史

计算机中加入操作系统实现多个程序同时执行,主要基于以下原因:

  • 资源利用率

    在某些情况下,程序必须等待某个外部操作执行完成,例如输入输出操作,在等待时程序无法执行其他任务,若是在等待的同时可以运行另一个程序,无疑会提高资源利用率。

  • 公平性

    不同的用户和程序对计算机的资源有着同等的使用权,一个高效的运行方式是通过粗粒度的时间分片(Time Slicing)使用户和程序能共享计算机资源,而不是一个程序执行完在执行下一个。

  • 便利性

    在计算多个任务时应该编写多个程序,每个程序执行一个任务并在必要时相互通信,这比只实现一个程序来计算所有用任务更容易实现

线程优势

  • 发挥多处理器的强大能力

    多线程程序可以同时在多个处理器上执行

  • 建模的简单性

    将复杂并且异步的工作流进一步分解成一组简单并且同步的工作流,每个工作流在一个单独的线程中进行,并在特定的同步位置进行交互

  • 异步事件的简化处理

    单线程服务器使用非阻塞I/O,要远远复杂于同步I/O,且容易出错。每个请求都拥有自己的处理线程,在处理某个请求时发生的阻塞将不会影响其他请求的处理。

  • 相应更灵敏的用户界面

    将长时间运行的任务放在一个单独的线程中运行,事件线程就能及时地处理界面事件,从而使用户界面具有更高的灵敏度

风险

  • 安全性问题

    线程安全性可能是非常复杂的,在没有充足同步的情况下,多个线程中的操作执行顺序是不可预测的,甚至会产生奇怪的结果。

    @NotThreadSafe
    public class UnsafeSequece {
        private int value;
        public int getNext() {
            return value++;
        }
        public static void main(String[] args) {
            //实例化对象后,一只调用,值会一直增加
            UnsafeSequece unsafeSequece = new UnsafeSequece();
            for (int i = 0; i < 10; i++) {
                System.out.println(unsafeSequece.getNext());
            }
        }
    }
    

    多个线程共享内存地址空间并且并发运行时,可能会访问或修改其他线程正在使用的变量,要使多线程程序行为可预测,必须对共享变量的访问操作进行协同,才不会彼此干扰。

    @ThreadSafe
    public class Sequence {
    	//第二章中介绍GuardedBy,这个标注说明了同步策略
        @GuardedBy("this")
        private int Value;
        public synchronized int getNext() {
            return Value++;
        }
        public static void main(String[] args) {
            Sequence sequence = new Sequence();
            for (int i = 0; i < 10; i++) {
                System.out.println(sequence.getNext());
            }
        }
    }
    
  • 活跃性问题

    死锁:两个线程相互等待对方释放资源

    饥饿:

    ​ 多线程并发时,优先级低的线程永远得不到执行

    ​ 线程被永远阻塞在等待进入 同步块的状态

    ​ 等待的线程永远不被唤醒

    活锁:任务或执行者都没有被阻塞,由于某些条件未满足,导致重复尝试-失败的过程

  • 性能问题

    服务时间过长、响应不灵敏、吞吐率过低、资源消耗过高、可伸缩性较低等

你可能感兴趣的:(Java,并发)