浅析Java 中数据访问一致性、happen-before、同步和原子访问的概念

  在多线程的应用中,当一个线程访问一个数据时,读到的数据可能不是最新的,这就是因为存在有另一个线程同时对这个数据做了修改,而读取不到正确的、最新的数据,这种问题叫内存数据访问一致性的问题 (Memory Consistency Errors)。即读取的数据是错误的。引起这种现象的原因是:多个线程对同一个数据同时访问,没有先来后到的规则,随意修改。出现这种现象称作是线程干扰(Thread Interference)。意思是另一个线程干扰到当前线程的数据访问。
  所以要想读取到正确、最新的数据,就需要建立“先来先修改,后来后修改”,“后来者读取的结果总是最新的”的规则。这种规则是happen-before机制。happen-before可以自动建立,也可以手动建立。 同步机制(Synchronization)就是其规则之一(这也是手动建立happen-before关系手段之一,使同步代码的结果对"后来者"是可见的。)。Java中可以使用关键字synchronized建立同步关系。synchronized可修饰方法(Synchronized Methods),可以修饰代码块(Synchronized Statements),使代码块具有同步访问的效果。较深层次说,这种同步的原理是依靠内在锁(Intrinsic Locks)的支持。每一个对象会拥有一个内在锁,当一个线程访问该对象数据前,需要先获取该对象的内在锁,在该线程获取到内在锁到释放内在锁之前,其他的线程访问该对象时是获取不到锁的,这时其他的线程将会阻塞,直到获取内在锁的线程释放锁。获取到内在锁的线程,在拥有内在锁期间内,会独占该实例对象的资源而不会受干扰。另外,该对象中使用同一个内在锁的其他的同步方法的访问将不受限制。这就意味着,可以在同步方法中直接或间接调用拥有同一个内在锁的其他同步方法。这就是重用同步(Reentrant Synchronization)的概念。依靠重用同步,一个内在锁能被获取多次。
  在为解决数据访问一直性问题除此加锁机制之外,原子访问(Atomic Access)也是其手段之一。原子访问将多个步骤视为一步。其中任何都必须成功,才视为整体的一步成功;其中任何一步失败,都视为整体的失败,原子操作不会存在中间状态:要么完全发生,要么不会发生。原子操作不会被多个线程交错执行,所以不用担心线程干扰问题。但不保证总是能解决内存一直性问题。使用关键字volatile可以降低这种风险,该关键字也是手动建立happen-before方法之一。使用原子操作访问数据比同步代码访问数据更加有效,JDK中提供了一些原子操作的方法,其实现不依赖同步机制。
  总而言之,因存在线程干扰,导致数据被异常修改,引发内存数据访问一致性问题,可通过手动建立happen-before机制制约,这就包括建立锁机制或原子操作机制等。

参考文档.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值