java锁知识点小记

java锁的知识点小记:
一.什么是线程安全:
标准定义:多个线程访问一个对象,如果不用考虑这些线程的调度和交替执行,也不需要进行额外的同步,或者在调用方法进行任何其他的协调,调用这个对象的行为都能得到正确结果,则称线程安全。
如上定义为侠义的线程安全,实际上,线程安全又分为五种强度,从强到弱以此为“不可变”,“绝对线程安全”,"相对线程安全",“线程兼容”和“线程对立”。
1.不可变:不可变的对象一定是线程安全的,无论是对象的方法实现还是方法的调用者,都不需要再采取任何的安全保障措施。
2.绝对线程安全:“不管运行环境如何,调用者都不要任何额外的同步措施”通常需要付出很大代价。Java API中标明线程安全的类,大多数都不是绝对线程安全。
3.相对线程安全:就是我们通常所说的线程安全,要保证对这个对象单独操作是线程安全的,我们在调用时候不需要做额外的保障措施。但对一些特定顺序的连续调用,就可能需要在调用端使用额外的同步手段保证调用的正确性。
4.线程兼容:线程兼容是指对象本身并不是线程安全的,但可以通过在调用端正确使用同步手段来保证对象在并发环境中可以安全的使用。
5.线程对立:指无论调用端是否采取了同步措施,都无法在并发环境中使用的代码。

二.锁的类型:
宏观上说锁分为悲观锁(阻塞同步)和乐观锁(非阻塞同步)
乐观锁(非阻塞同步):及一种乐观思想,先进行操作,如果没有其他线程争用共享数据,那操作就成功了,如果共享数据有争用,产生了冲突,就再采取其他的补偿措施。
乐观锁需要操作和冲突检测这两部具有原子性,只能靠硬件完成,硬件保证一个从语义上需要多个操作步骤的行为只用一个指令就可以完成,这包括:
1.测试并设置
2.获取并增加
3.交换
4.比较并交换(compareAndSwap CAS)
5.加载链接/条件存储
java的乐观锁主要靠CAS来完成,cas需要三个操作数,分别为操作v操作变量的内存地址,A旧的预期值,B新值。当V所存储的值为预期值A时,则更新新值,上述比较和交换操作是原子的。
java的CAS操作是通过sun.misc.Unsafe类实现的,java.util.concurrent包中的原子类都是建立在CAS的基础上的。如AtomicInteger的getAndIncrement()操作。

public final int getAndIncrement() {
        return unsafe.getAndAddInt(this, valueOffset, 1);
}

unsafe的getAndAddInt函数则是判段cas操作是否成功,如不成功,则一直CAS

    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }

compareAndSwapInt包含四个参数,var1指向对象的引用,var2操作变量在此对象中的地址偏移量,var5期望值,var5+var4目标值

悲观锁(互斥同步):总认为不去做正确的同步措施,就会出现问题,无论共享数据是否存在竞争,都会进行加锁,java中最基本的互斥同步手段就是synchronized关键字。

三.synchronize底层实现原理
java1.5之前都是使用synchronize实现,synchronize关键字可用来修饰方法,对象或者静态方法。
1.1synchronize方法
synchronize方法同步是隐式的,及无需通过字节码指令来控制,它实现在方法调用和返回操作中。jvm可以从常量池方法表的中的ACC_SYNCHRONIZED的访问标志确定一个方法时候为同步方法。方法调用是调用指令会检查该标识,如果为同步方法则执行线程将先持有monitor,再去执行方法。
1.2synchronize代码块
synchronize关键字进行编译后,会在同步代码块前后形成monitorenter和monitorexit指令,该指令后面跟着一个reference类型的参数指明要锁定或解锁的对象。在执行monitorenter指令时,会去获取对象的锁,如果对象没有被锁定,或者当前线程已经拥有了那个对象的锁,则锁的计数器+1.执行monitorexit指令时锁的计数器-1.如果获取锁失败,则当前线程就要进入阻塞状态。
1.3monitor(监视器锁/管程)的实现方式。
重量级锁是通过monitor实现的,锁的标志位为10,对象头中的指针指向monitor对象的起始地址。在java虚拟机中,monitor是由ObjectMonitor实现。位于\openjdk-jdk8u-jdk8u\openjdk-jdk8u-jdk8u\hotspot\src\share\vm\runtime包中。

 ObjectMonitor() {
    _header       = NULL;//对象头
    _count        = 0;//锁计数器
    _waiters      = 0,//等待线程数
    _recursions   = 0;//重入次数
    _object       = NULL;
    _owner        = NULL;//指向获得ObjectMonitor对象的线程
    _WaitSet      = NULL;//处于wait状态的线程,会被加入waitset
    _WaitSetLock  = 0 ;
    _Responsible  = NULL ;
    _succ         = NULL ;
    _cxq          = NULL ;
    FreeNext      = NULL ;
    _EntryList    = NULL ;//处于等待锁block状态的线程,会被加入entryset
    _SpinFreq     = 0 ;
    _SpinClock    = 0 ;
    OwnerIsThread = 0 ;
    _previous_owner_tid = 0;
  }

当多个线程访问同一个代码块时,首先会进入_EntryList集合,当对象获得到线程的monitor后,进入owner区域并将owner变量设置为当前线程同事count+1.若调用wait方法,释放当前持有的monitor,owner变量恢复为null,count-1.同时当前线程进入waitset等待被唤醒。若当前线程执行完毕也将释放monitor并复位变量的值。

四.jvm对锁的优化
4.1偏向锁
是jdk1.6后引入的一项优化,目的是消除数据在无竞争情况下的同步同步原语,偏向所会偏向第一个获得他的线程,如果之后该锁没有被其他线程获取,则偏向线程不需要再同步。
当虚拟机启用偏向锁,那么当锁对象第一次被虚拟机获取时,会将mark word中的标志位设置为01,同时使用cas操作更新markword中的threadID。
当另外一个线程尝试获取这个锁时,偏向模式宣告结束,根据锁对象是否被锁定来判断,撤销偏向恢复为未锁定(标志位为01)或升级为轻量级锁

4.2轻量级锁
轻量级锁是相对于传统锁使用操作系统互斥量而言的,目的是为了减少传统锁使用操作系统互斥量的性能消耗。
轻量级锁在代码进入同步块时,如果此同步对象没有被锁定(标志位为01),当前线程会在栈帧中创建一个名为锁记录的空间(lock record),用于存储当前对象的mark word拷贝。然后虚拟机CAS将mark word更新为指向lock record的指针。如果更新操作成功了,则这个线程就拥有了该对象的锁。并且将mark word锁标志位改为“00”,即表示此对象处于轻量级锁定状态。
如果更新操作失败了,虚拟机首先会检查对象的Mark word是否指向当前线程的栈帧,如果只说明当前线程已拥有这个对象的锁,那就可直接进入同步块执行,否则说明这个锁已经被抢占,轻量级锁需要膨胀为重量级锁,mark word中的标志位改为10.
轻量级锁解解锁过程也是通过CAS完成的,如果对象的mark word仍指向线程的锁记录,就用cas操作将对象当前mark word与栈帧中赋值的mark word替换过来,如果替换失败,说明有其他线程尝试获取该锁,就要在释放锁的同时唤醒被挂起的线程。

五.java锁升级的原理:
未完待续。。。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容