Java中的线程安全与实现

来源:互联网 发布:广州易娱网络怎么样 编辑:程序博客网 时间:2024/06/10 17:38

线程安全的定义:当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象是线程安全的。

Java语言中的线程安全

按照线程安全的“安全程度”由强至弱来排序,可以将Java中各种操作共享的数据分为5类:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立。

不可变

不可变(Immutable)的对象一定是线程安全的,无论是对象的方法实现还是方法的调用者,都不需要再采取任何的线程安全保障措施。

Java中,如果共享数据是一个基本数据类型,那么只要在定义时使用final关键字就可以保证它不可变。如果是一个对象,那就需要保证对象的行为不会对其状态产生任何影响才行。如java.lang.String类的对象,它是典型的不可变对象,调用它的API不会影响原来的值,只会返回一个新构建的对象。

绝对线程安全

绝对线程安全要完全满足上面的定义,在Java API中标注自己是线程安全的类,大多数都不是绝对的线程安全。

相对线程安全

就是通常意义上的线程安全,需要保证对这个对象单独的操作是线程安全的,在调用时无需做额外的保障措施,但是对于一些特定顺序的连续调用,可能需要在调用端使用额外的同步手段来保证调用的正确性。在Java中,大部分的线程安全的类都是这种类型。

线程兼容

对象本身并不是线程安全的,但是可以通过在调用端正确的使用同步手段来保证对象在并发环境中可以安全的使用,平时说的一个类不是线程安全的,指的大多数都是这一种情况。

线程对立

无论调用端是否采用了同步措施,都无法在多线程环境下并发使用的代码。
这里写图片描述

线程安全的实现方法

本节主要讲述虚拟机如何实现同步与锁机制的内容。

互斥同步

互斥同步(Mutual Exclusion & Synchronization)是常见的一种并发正确性保障手段,同步是指在多个线程并发访问数据时,保证共享数据在同一时刻只被一个(或是一些)线程使用。而互斥是实现同步的一种手段,临界区(Critical Section)、互斥量(Mutex)和信号量(Semaphore)都是主要的互斥实现方式。互斥是因,同步是果;互斥是方法,同步是目的。

非阻塞同步

互斥同步最主要的问题是进行线程阻塞和唤醒带来的性能问题,因此这种同步成为阻塞同步(Blocking Synchronization)。其属于悲观的并发策略,总是认为只要不去做正确的同步措施,那么肯定就会出现问题。

现在有了另一个选择,基于冲突检测的乐观并发策略,就是先进行操作,如果没有其他线程争用共享数据,那操作就成功了;如果共享数据有争用,产生了冲突,就再采取其他的补偿措施(重试直到成功为止),这种乐观的并发策略的许多实现都不需要把线程挂起,因此称为非阻塞同步(Non-Blocking Synchronization)。

无同步方案

要保证线程安全,并不一定要进行同步,二者没有因果关系。如果一个方法本来就不设计共享数据,就无需同步措施,因此有一些代码天生是线程安全的,比如下面两类:
这里写图片描述
这里写图片描述

原创粉丝点击