2.Java并发编程实战--第二章

来源:互联网 发布:ubuntu ant android 编辑:程序博客网 时间:2024/06/05 09:51

  • 构建线程安全应用程序
    • 线程安全性
    • Servlet 的线程安全性
    • 同步
      • 同步与 volatile
    • 高级并发对象

构建线程安全应用程序

线程安全性

如果其他线程企图访问一个处于不可用状态的对象,该对象将不能正确响应从而产生无法预料的结果,如何避免这种情况发生是线程安全性的核心问题。

有这样的定义:“一个类在可以被多个线程安全调用时就是线程安全的”。

类要成为线程安全的,首先必须在单线程环境中有正确的行为。

正确性与线程安全性之间的关系非常类似于在描述 ACID(原子性、一致性、独立性和持久性)事务时使用的一致性与独立性之间的关系:从特定线程的角度看,由不同线程所执行的对象操作是先后(虽然顺序不定)而不是并行执行的。

Bloch 给出了描述五类线程安全性的分类方法:不可变、线程安全、有条件线程安全、线程兼容和线程对立。


Servlet 的线程安全性

Servlet 体系结构是建立在 Java 多线程机制之上的,它的生命周期是由 Web 容器负责的。当客户端第一次请求某个 Servlet 时,Servlet 容器将会根据 web.xml 配置文件实例化这个Servlet 类。当有新的客户端请求该 Servlet 时,一般不会再实例化该 Servlet 类,也就是有多个线程在使用这个实例。Servlet 容器会自动使用线程池等技术来支持系统的运行。
这样,当两个或多个线程同时访问同一个 Servlet 时,可能会发生多个线程同时访问同一资源的情况,数据可能会变得不一致。所以在用Servlet 构建的 Web 应用时如果不注意线程安全的问题,会使所写的 Servlet 程序有难以发现的错误。
Servlet 的线程安全问题只有在大量的并发访问时才会显现出来,并且很难发现,因此在编写 Servlet 程序时要特别注意。线程安全问题主要是由实例变量造成的,因此在 Servlet 中应避免使用实例变量。如果应用程序设计无法避免使用实例变量,那么使用同步来保护要使用的实例变量,但为保证系统的最佳性能,应该同步可用性最小的代码路径。


同步

同步是围绕被称为内在锁(intrinsic lock)或者监视器锁(monitor lock)的内部实体构建的,强制对对象状态的独占访问,以及建立可见性所需的发生前关系。
Java 提供了 synchronized 关键字来支持内在锁。Synchronized 关键字可以放在方法的前面、对象的前面、类的前面。

同步与 volatile

volatile是轻量级的synchronize,它在多处理器开发中保证了共享变量的“可见性”,即当一个线程修改一个共享变量时,另外一个线程可以读到这个修改的值。

任何被不同线程所共享的可变值应该总是被同步的访问以防止发生干扰,然而同步是需要代价的。Java 可以保证对任何变量的读写都是原子性的,原子(atomic)操作是必须同时完成的操作,这样变量就只会持有某个线程写入的值,而绝不会持有两个不同线程写入的部分交叉混合的值。这意味着原子变量只能有一个线程来写,多个线程来读,因此不需要对他的访问进行同步以防止数据被破坏,因为这些访问之间不存在互相干扰的可能性。但这对“获取-修改-设置”(如++操作)没有任何帮助,这种操作需要同步。
需要注意的是,原子访问并不能保证线程总是会读取变量最近的写入值,如果没有同步,一个线程的写入值对另一个线程可能永远都不会是可见的。有很多因为会影响一个线程写入的变量何时会对另一个线程变为可见的。当缺乏同步机制时,不同线程发现被更新变量的顺序也可以完全不同。 在确定内存访问如何排序以及合适,可以确保他们可见时所使用的规则被称为 Java 编程语言的内存模型。

Java 提供了一种同步机制,它不提供对锁的独占访问,但同样可以确保对变量的每一个读取操作都返回最近写入的值,这种机制就是只用 volatile 变量。字段变量可以用修饰符volatile 来声明,volatile 变量的写入操作将与随后所有这个变量的读取操作进行同步。
volatile 变量并没有提供可以跨多个动作的原子性,经常被用作简单的标记以表示发生了某个事件,或者被用来编写无锁算法(lock-free)。
将变量设置为 volatile 所产生的另一个效果就是可以确保读写操作都是原子性的。
volatile实现机制:

  • 1 .Lock前缀指令会引起处理器缓存写回内存。
  • 1 .一个处理器的缓存回写到内存会导致其他处理器的缓存无效。

高级并发对象

JDK5.0 以后的版本都引入了高级并发特性,并且新的版本在不断的补充和完善。大多数的特性在 java.util.concurrent 包中实现,Java 集合框架中也有新的并发数据结构。主要增加的高级并发对象有:Lock 对象,执行器,并发集合、原子变量和同步器。

原创粉丝点击