java并发理解

来源:互联网 发布:淘宝发布产品不同型号 编辑:程序博客网 时间:2024/06/04 18:39

1、为什么需要多线程?

充分利用多核CPU的能力

单线程阻塞,这个线程将做不了任何事情,无响应

在事件驱动模型下,需要有多个线程同时服务


2、为什么需要并发?

多线程存在资源的竞争问题,如I/O资源,共享变量等。在进程中,这些竞争都由OS处理,可是多线程程序需要程序员来控制,否则就得尝试函数式编程,如Erlang。

如果一个线程将一共享的资源置于不合理的状态,另一个资源试图访问的时候,就会出现问题。


3、仅用互同步来解决资源竞争问题可行嘛?不行又如何解决这个问题?

所谓同步,就是对资源的串行访问。可以通过:

  • 原子操作:所谓原子操作,就是该操作完成之前,线程调度器不能启动其他线程对同一资源进行访问。如long/double的读写在JVM中是两次操作,是非原子的,加上volatile关键字,实现读写的原子行,这样long/double类型的关键字就不会在读写完成之前被其他线程改动了。
  • synchornized 互斥访问一个代码块
  • 显式锁lock  互斥访问一个代码块


仅仅通过互斥访问,处理共享资源的竞争,其他等待访问的线程就会阻塞等待,这样性能显然不高。为了改变这种状态,java并发中提供了一些优化机制:如

ReadWriteLock   读写锁,可多线程同时读,但若有一个线程试图写操作时,其他线程都得等它完成。

免锁容器: 如CopyOnWriteArrayList,如果一线程试图读一数组,就会将copy一份该数组的副本,其他读线程同时还可以读原数组,但不允许多个写线程同时操作。

ConcurrentHashMap : 分段分别加读写锁,如果仅有几段在进行写操作,其他段还可以读。

Condition : 用于线程间的协作!lock对象可关联Condition对象,从而协调多线程对竞争资源的逻辑依赖关系,如一个读线程在维护数组非空的Contion对象notEmpty上等待,直到另外一个生产线程填充了该数组,并调用signalAll()来提醒等待在notEmpty上的线程可以进行下一步了。显然,仅仅互斥,是没法表达这种逻辑关系的!


我们发现上面并发中三种优化机制,解决了仅仅互斥的所遇到的性能问题,和线程间协作的问题!

所谓线程间的协作,即线程使用资源之前,会考虑该资源的状态是否在“可使用”的条件下,不可用,就阻塞等待,直到其他进程使这一条件满足,再通知它!


原创粉丝点击