并发编程读书笔记(一)

java并发编程是java程序员必须要会的知识,虽然写下的东西还比较肤浅,但是自己消化加上自己理解的东西也是好的…这一篇主要介绍了多线程的一些简单的内容。

简介

进程

在没有操作系统之前,程序可以调用机器的所有资源从头执行到尾。这样的程序既复杂而且效率不高。操作系统出现之后,计算机可以允许多个独立的程序同时运行,称之为***进程(process)***。这些进程由操作系统来分配资源例如内存、文件句柄、安全认证等。如果需要的话,各个进程之间还可以通过各种各样的通信机制来交流,如sockets,signal handler,shared memory,semaphores和files。

进程的优点
  • 资源利用:有时候程序需要等待其他的操作比如input和output,这个时候如果让其他程序来利用计算机的资源会更加有效。
  • 公平性:多个用户和程序对计算机的资源有同样的权利,让它们在设计良好的时间切片下轮流执行,比让一个程序从头执行完再执行另一个程序更加公平。
  • 方便性:写多个程序让每个程序执行一个任务,必要的时候互相交流,最后再由一个程序来执行所有任务的编程模型更加简单而且更受人喜欢。

一个善于利用时间的人会在起床后先烧水,然后去刷牙洗脸,而不是刷牙洗脸完再去烧水。程序也是这样。

线程

同样地,线程(Thread) 的发展受到了进程发展的启发:在一个进程内可以同时包括多个线程。它们共享进程的资源如内存和文件句柄,但每个线程还拥有自己的程序计数器,栈,和本地变量。并且,线程还可以利用多处理器系统;同一个线程内的进程们可以同时在多个CPU上执行。
线程有时候也叫轻量级进程,几乎所有的现代操作系统都把线程作为调度的基本单元。

多线程优缺点

当合理使用时,多线程能够降低程序开发和维护的成本,提高应用的性能。多线程能将异步的程序任务流变成几乎顺序执行的任务流,而且代码写起来更简单,易读和易维护。
多线程对提高用户界面的响应的GUI应用和高吞吐高性能的服务端程序(如servlets和RMI等)很有用,它们对JVM的垃圾回收器也很有用。
正因为多个线程独立执行的同时共享了进程的变量和堆内存,如果没有显式的同步操作,一个线程可能会修改另一个线程正在使用的变量,从而带来不可预料的后果。
当我们使用多线程时,必须关注以下几点:

  • safety

由于各个线程的执行顺序是不可预测的,有时候会导致令人意外的结果。如:

@NotThreadSafe
public class UnsafeSequence{
    private int value;
    public int getNext(){
        return value++;
    }
}

假设上述代码有A,B两个线程,很有可能每个线程从共享内存同时读取了value值,同时在本地方法中自增,最后同时写回新的值到共享内存。这样两个线程执行后得到了同样的结果,是不正确的。

上述代码可以改为线程安全,如下所示:

@ThreadSafe
public class Sequence{
    private int value;
    public synchronized int getNext(){
        return value++;
    }
}
  • liveness

当一个线程到达一种永远不能执行的状态,这就叫liveness failure。这样的情况有:在顺序执行的程序中,前面的代码出现了死循环导致后面的代码不能执行;而在多线程的程序中,如果A线程在等待B线程正在占有的资源,然后B线程永远都没有没有释放它,那么A线程不能继续执行。典型的场景有dead lock,starvation,livelock

  • performance

程序性能表现在很多方面,如响应时间,吞吐量,资源消耗,扩展性等。多线程带来了一些性能的消耗—上下文切换。CPU暂停当前的线程进入下一个线程需要保存和恢复各个线程执行的上下文,这个过程占用了CPU时间;当各个线程共享数据时,使用同步机制妨碍了编译器的优化和内存缓存的刷新失效,同时在共享内存中引起同步traffic。


FAQ

并发和并行的区别

并行是并发概念的一个子集。并发是系统中存在多个线程,如果多个线程可以在不同的CPU上同时执行,那么这个系统也支持并发。如果只有一个CPU,多个线程只能在这一个CPU上交替执行,那么这个系统是并发系统但不支持并行。

异步和同步的区别

同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)

同步是为了保证数据结果的正确性,在多线程的环境下,同一时间只能有一个线程在运行,且调用该线程运行完得到结果时才能return。唯一的资源适合同步,如数据库的写操作。实现方式例如:jvm的关键字synchronized,lock等。

异步是为了充分利用资源,加快运行速度,同一个时间有多个程序在运行。程序调用不需要等待结果返回,而是等被调用者用状态来通知调用者,或者通过回调函数处理调用。互斥的资源适合异步,如数据库的读操作。实现方式例如js的ajax,node技术和java的多线程技术。

阻塞和非阻塞

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。

阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

  • 同步阻塞:我打电话问书店老板问有没有《java并发编程实践》这本书,老板说我找一下,我一直拿着电话等着老板的回复。
  • 同步非阻塞:我打电话问书店老板问有没有《java并发编程实践》这本书,老板说我找一下,我乘机刷一下朋友圈,过几分钟再来check老板有没有回复。
  • 异步阻塞:我发个短信问书店老板问有没有《java并发编程实践》这本书,然后一直盯着手机等着老板的回复。
  • 异步非阻塞:我发个短信问书店老板问有没有《java并发编程实践》这本书,然后一打开电脑开始看剧,等到手机叮地一声提醒我老板回复了再去和老板处理买书的事情。

在上述例子中,打电话和发信息代表同步和异步的通信机制,而我的反应代表阻塞和非阻塞的状态。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值