`
yangyi
  • 浏览: 115355 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

浅谈Java中的同步的方法和原理

阅读更多
Java的内存模型中Thread会附有自己的堆栈,寄存器,必要时需要和主存即heap之间同步。
可以使用Synchornized关键字和Concurrent包中的Lock可以保证线程互斥和可见性。

互斥性体现在类锁或者对象锁上,每个对象自身都包含一个监视器,该监视器是一个每次只能被一个线程所获取进入的临界区,可以通过wait和notify来退出和准入临界区。可以看出这是一个生产者-消费者的模型。而Concurrent包中的Lock为了能够获得更好的性能和更好的扩展性,以及不依赖于关键字的可读代码,自己实现了这样一个生产消费队列,也就是AbstractQueuedSynchronizer,被称为AQS的机制。每个Lock都内置了一个AbstractQueuedSynchronizer。需要说明的是AbstractQueuedSynchronizer内部实现采用了CAS机制,通过getState, setState, compareAndSetState访问控制一个32bit int的形式进行互斥。

那么可见性是如何保证的呢?

对于关键字的同步机制,其实可见性就是线程和主存之间的同步时机问题。共有4个时间点需要注意:
1 获取或释放类锁/对象锁的时候。Thread保证reload/flush全部变更
2 volatile就是flush on write或者reload on read
3 当线程首次访问共享变量时,可以得到最新的结果。
题外:所以在构造方法中公布this时很危险的。简单的说,就是构造时不逃脱任何变量,不开启新的线程,只做封装。关于安全构造,请参考
http://www.ibm.com/developerworks/cn/java/j-jtp0618/#resources
4 线程结束时,所有变更会写回主存

关于Concurrent Lock如何实现可见性的问题,Doug Lea大侠,只在他的论文中提到,按照JSR133,Unsafe在getState, setState, compareAndSetState时保证了线程的变量的可见性,不需要额外的volatile支持,至于具体这些native做了哪些magic就不得而知了,总之,最后的contract就是保证lock区间的共享变量可见性。开发团队被逼急了就这样回答:
引用
There seems to be a real reluctance to explain the dirty details. I think the question was definitely understood on the concurrent interest thread, and the answer is that synchronized and concurrent locking are intended to be interchangable in terms of memory semantics when implemented correctly. The answer to matfud's question seems to be "trust us."

不过这个地方的确是开发团队给我们用户迷惑的地方,在同样应用了CAS机制的Atomic类中,都内嵌了volatile变量,但是再lock块中,他告诉我们可以保证可见性。

感兴趣的同学可以下面的两个thread和Doug Lea的thesis:
http://altair.cs.oswego.edu/pipermail/concurrency-interest/2005-June/001587.html
http://forums.sun.com/thread.jspa?threadID=631014&start=15&tstart=0
http://gee.cs.oswego.edu/dl/papers/aqs.pdf
分享到:
评论
11 楼 mercyblitz 2010-07-20  
yangyi 写道
mercyblitz 写道
yangyi 写道
mercyblitz 写道
yangyi 写道
找到答案了,这个技术叫做Piggybacking,我还不知道怎么翻译。总之就是利用既有的happens-before来优化,而不是通过同步来产生新的happens-before。


Atomic类利用的是CAS操作,这个需要硬件(指令)支持。


AQS也是CAS的吧,而且CAS对于操作的原子变量内存模型语义和synchronization是等同的,CAS如果不考虑Piggybacking并不能保证全部共享变量的可见性。这里说的是Concurrent Lock可见性的问题。


AQS利用了CAS操作,最开始它的state信息利用了内存屏蔽原语volatile。我的理解是,AQS利用偏序(Happens-Before)是没有问题的,因为在执行上这些线程并没有区别,因为只要确保只有一个线程在工作,其他线程被park掉。那么AQS不需要同步synchronized原语,照样可以工作良好。因此Happens-Before的可见性,不会影响线程的工作。相反,Non-blocking 同步的性能更加。

你的理解正确,这就是Piggybacking做的事情


如果感兴趣的话,可以看看Nonblocking lock会出现ABA问题。

http://en.wikipedia.org/wiki/ABA_problem

欢迎讨论。
10 楼 yangyi 2010-07-20  
mercyblitz 写道
yangyi 写道
mercyblitz 写道
yangyi 写道
找到答案了,这个技术叫做Piggybacking,我还不知道怎么翻译。总之就是利用既有的happens-before来优化,而不是通过同步来产生新的happens-before。


Atomic类利用的是CAS操作,这个需要硬件(指令)支持。


AQS也是CAS的吧,而且CAS对于操作的原子变量内存模型语义和synchronization是等同的,CAS如果不考虑Piggybacking并不能保证全部共享变量的可见性。这里说的是Concurrent Lock可见性的问题。


AQS利用了CAS操作,最开始它的state信息利用了内存屏蔽原语volatile。我的理解是,AQS利用偏序(Happens-Before)是没有问题的,因为在执行上这些线程并没有区别,因为只要确保只有一个线程在工作,其他线程被park掉。那么AQS不需要同步synchronized原语,照样可以工作良好。因此Happens-Before的可见性,不会影响线程的工作。相反,Non-blocking 同步的性能更加。

你的理解正确,这就是Piggybacking做的事情
9 楼 mercyblitz 2010-07-20  
yangyi 写道
mercyblitz 写道
yangyi 写道
找到答案了,这个技术叫做Piggybacking,我还不知道怎么翻译。总之就是利用既有的happens-before来优化,而不是通过同步来产生新的happens-before。


Atomic类利用的是CAS操作,这个需要硬件(指令)支持。


AQS也是CAS的吧,而且CAS对于操作的原子变量内存模型语义和synchronization是等同的,CAS如果不考虑Piggybacking并不能保证全部共享变量的可见性。这里说的是Concurrent Lock可见性的问题。


AQS利用了CAS操作,最开始它的state信息利用了内存屏蔽原语volatile。我的理解是,AQS利用偏序(Happens-Before)是没有问题的,因为在执行上这些线程并没有区别,因为只要确保只有一个线程在工作,其他线程被park掉。那么AQS不需要同步synchronized原语,照样可以工作良好。因此Happens-Before的可见性,不会影响线程的工作。相反,Non-blocking 同步的性能更加。
8 楼 yangyi 2010-07-20  
mercyblitz 写道
yangyi 写道
找到答案了,这个技术叫做Piggybacking,我还不知道怎么翻译。总之就是利用既有的happens-before来优化,而不是通过同步来产生新的happens-before。


Atomic类利用的是CAS操作,这个需要硬件(指令)支持。


AQS也是CAS的吧,而且CAS对于操作的原子变量内存模型语义和synchronization是等同的,CAS如果不考虑Piggybacking并不能保证全部共享变量的可见性。这里说的是Concurrent Lock可见性的问题。
7 楼 mercyblitz 2010-07-20  
yangyi 写道
找到答案了,这个技术叫做Piggybacking,我还不知道怎么翻译。总之就是利用既有的happens-before来优化,而不是通过同步来产生新的happens-before。


Atomic类利用的是CAS操作,这个需要硬件(指令)支持。
6 楼 yangyi 2010-07-19  
找到答案了,这个技术叫做Piggybacking,我还不知道怎么翻译。总之就是利用既有的happens-before来优化,而不是通过同步来产生新的happens-before。
5 楼 mercyblitz 2010-07-18  
CAS和LL/SC操作都属于Nonblocking Synchronization,能够保证是Happens-Before的偏序,但是只能保证有限的正确性,比如SUM求和等。但是Lock能够保证读写的顺序。

比如,顺序定义如下:T1(W) -> T2(R) -> T3(W),如果HB的关系,那么T2会看到T3写入以后的结果。而Lock,就能够保证顺序。

4 楼 areshowl 2010-07-13  
既然是浅谈,为何如此抽象。。。。。
3 楼 二手烟民 2010-07-12  
读不懂,lz写的不够系统不够详细,对于我这种初学者太费力了!
2 楼 qianhd 2010-07-11  
mark~~
字数补丁
1 楼 risemanjavaeye 2010-07-11  
楼主能详细或举例解释一下“不逃脱任何变量”中逃脱吗?是英文escape吗?

相关推荐

    Java同步机制浅谈

    ### Java同步机制浅谈 #### synchronized关键字的作用及应用 在Java多线程环境中,`synchronized`关键字扮演着至关重要的角色。它可以帮助开发者确保多线程环境下的数据一致性,防止因并发访问导致的数据错误。本...

    浅谈java连接池

    - 在Java中,通过`synchronized`关键字实现线程同步,确保连接的并发安全。 2. **多数据库服务器与多用户支持** - 设计单例模式的连接池管理类,根据配置文件中的数据库信息动态创建和管理不同的连接池。 3. **...

    浅谈java!

    本文基于给定的文件信息,详细阐述Java自学过程中的一些关键知识点及学习策略,旨在帮助那些希望通过自学Java来提升技能或寻找职业机会的学习者们。 #### 一、JavaSE基础学习 JavaSE是Java标准版的基础,对于所有...

    浅谈Java中的atomic包实现原理及应用

    Java中的atomic包实现原理及应用 本文主要介绍了Java中的atomic包实现原理及应用,涉及Atomic在硬件上的支持、Atomic包简介及源码分析等相关内容。 Atomic在硬件上的支持 在单处理器系统中,能够在单条指令中...

    浅谈JAVA集合框架及其应用.zip

    Java集合框架是Java编程语言中一个至关重要的组成部分,它为数据存储、管理和处理提供了丰富的类和接口。这个框架包括了数组、链表、队列、堆栈、映射等多种数据结构,极大地提高了开发效率和代码的可读性。在本文中...

    浅谈Java中ABA问题及避免

    浅谈Java中ABA问题及避免 Java中的ABA问题是指在使用Compare-And-Swap(CAS)操作时可能出现的一种问题。该问题的产生是由于CAS操作的原子性和并发环境中的线程执行顺序的不确定性。ABA问题的出现可能会导致程序的...

    Java分布式应用学习笔记06浅谈并发加锁机制分析

    ### Java分布式应用学习笔记06浅谈并发加锁机制分析 #### 1. 前言 在深入探讨Java中的并发加锁机制之前,我们有必要回顾一下多线程环境下的一些基本概念和技术。之前的多线程调度、并发调度以及线程加锁安全等内容...

    Oracle RAC原理浅谈.pptx

    用户进程与服务器进程交互,PGA(程序全局区)和共享内存区域(如Java Pool和Large Pool)用于存储用户会话信息和特定任务的数据。 双节点Oracle RAC架构中,ABL、LMS、LMD、LMON、LCK0等是集群内的重要进程,它们...

    缓存技术浅谈

    这篇“缓存技术浅谈”可能是一篇深入解析缓存概念、原理及应用的博客文章,结合PPT形式提供了更直观的理解。以下是根据标题和描述可能涉及的一些核心知识点: 1. **缓存基本概念**:缓存是一种存储技术,用于临时...

    java基础PPT

    11. **JNI与JVM原理**:浅谈Java Native Interface(JNI),用于在Java程序中调用本地(非Java)代码,以及JVM的工作原理,包括类加载、内存管理和垃圾收集。 12. **案例分析**:可能包含一些简单的编程实例,帮助...

    浅谈Java的虚拟机结构以及虚拟机内存的优化

    方法区是JVM存储类型信息的地方,如类的全限定名、超类信息、访问修饰符,以及常量池、字段和方法信息等。值得注意的是,方法区也是垃圾回收的一部分,可以回收不再使用的类信息。 堆内存是所有线程共享的区域,...

    浅谈Java 并发的底层实现

    在Java中,volatile关键字和synchronized关键字是实现线程同步的重要工具。volatile确保了变量在所有线程间具有可见性,但无法保证原子性。例如,在上述代码示例中,`Go` 类的 `i++` 操作不是一个原子操作,因此并发...

    浅谈servlet3异步原理与实践

    浅谈servlet3异步原理与实践 本篇文章主要介绍了servlet3异步原理与实践,详细的介绍了servlet和异步的流程使用,具有一定的参考价值。 一、什么是Servlet Servlet 是基于 Java 的 Web 组件,由容器进行管理,来...

    AtomicInteger 浅谈

    《AtomicInteger 浅谈》 在Java编程中,原子性操作是并发编程中非常关键的一环,它确保了在多线程环境下数据的正确性和一致性。AtomicInteger是Java并发包java.util.concurrent.atomic中的一个类,提供了对单个整型...

    面试指南java

    - OverLoad与Override的区别:明确方法重载(Overload)和方法覆盖(Override)之间的区别。 - Collection与Collections的区别:知道Collection是集合框架的根接口,而Collections是一个工具类。 第三部分:Java...

    java程序员初学20道题

    浅谈JDBC的概念理解与学习 JDBC(Java Database Connectivity)是Java中用来对数据库进行统一访问、管理的一种机制。通过JDBC,开发人员可以使用标准Java API来连接不同的数据库管理系统。 - **JDBC驱动模型**:...

    Java面试指南.pdf

    - **5.4 序列化和反序列化**:介绍序列化的基本原理及其在Java中的实现方式。 - **5.5 Java实现浅克隆与深克隆**:说明Java中克隆机制的两种形式及其应用场景。 - **5.6 枚举可以序列化吗**:探讨枚举类型的序列化...

    java高手的文章合集1/3

    这个合集以“由一个简单的程序谈起”为主题,通过一系列文章深入浅出地介绍了Java语言的核心概念和技术。以下是这些文章可能涉及的重要知识点: 1. **Java入门**:文章可能从一个简单的“Hello, World!”程序开始,...

    浅谈多线程中的锁的几种用法总结(必看)

    "浅谈多线程中的锁的几种用法总结" 多线程编程中,锁机制是一种常见的同步机制,用于解决多线程之间的资源竞争问题。锁机制可以分为两种:互斥锁和读写锁。在 Java 中,ReentrantLock 和 ReentrantReadWriteLock 是...

    线程详解-打包(3 合1)下载

    《浅谈Windows中的多线程编程》文档可能以更通俗易懂的方式探讨Windows下的线程概念。它可能涵盖线程的生命周期、线程间交互的基本原理,以及处理线程安全问题的策略。文档可能会针对初学者,解释线程在日常软件开发...

Global site tag (gtag.js) - Google Analytics