zoukankan      html  css  js  c++  java
  • synchronized关键字

    概要

    synchronized能保证原子性、可见性、有序性。原理如下:

    原子性:synchronized编译后产生字节码指令monitorenter、monitorexit,这两个指令最终对应到JVM底层就是原子操作lock、unlock。

    可见性:对一个共享变量执行unlock前先把此变量的值从线程的工作内存同步到主内存。

    有序性:由于一个共享变量在同一时刻只允许一条线程对其执行lock操作,因此持有同一个锁的两个同步块只能串行进入。

    原理:(P391)

    synchronized编译后在同步块前后分别形成monitorenter、monitorexit字节码指令,这两个指令需要一个Reference类型参数指明要锁定和解锁的对象(没明确指定时根据synchronized修饰的是类方法还是实例方法取相应的Class对象或对象实例作为锁对象)。

    • 执行monitorenter时首先尝试获取对象的锁。若对象没被锁定或当前线程已拥有了该对象的锁,则锁计数加1;相应地,执行monitorexit时锁计数减1,计数为0时释放锁。
    • 若当前线程获取锁对象失败则阻塞等待,直到对象锁被占有该锁的另一个线程释放,并且当前线程抢到该锁。

    synchronized同步块对同一个线程来说是可重入的,不会出现把自己锁死的问题。

    下面详述

    synchronized用来修饰代码块或方法,其作用是让访问该方法或代码块的线程获取方法所属对象的同步锁,以实现同步操作。

    1、

    在java中,每一个对象有且仅有一个同步锁。这也意味着,同步锁是依赖于对象而存在;我们通过调用某对象的synchronized方来获取该对象的同步锁。
    我们将synchronized的基本规则总结为下面3条,并通过实例对它们进行说明。

    • 第一条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
    • 第二条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程仍然可以访问“该对象”的非同步代码块。
    • 第三条: 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的其他的“synchronized方法”或者“synchronized代码块”的访问将被阻塞。

    实例锁 -- 锁在某一个实例对象上。如果该类是单例,那么该锁也具有全局锁的概念。实例锁对应的就是synchronized关键字。
    全局锁 -- 该锁针对的是类,无论实例多少个对象,那么线程都共享该锁。全局锁对应的就是static synchronized(或者是锁在该类的class或者classloader对象上)。

    关于“实例锁”和“全局锁”有一个很形象的例子:

    pulbic class Something {
      public synchronized void isSyncA(){}
      public synchronized void isSyncB(){}
      public static synchronized void cSyncA(){}
      public static synchronized void cSyncB(){}
    }
    假设,Something有两个实例x和y。分析下面4组表达式获取的锁的情况。
    (01) x.isSyncA()与x.isSyncB() //不能同时访问
    (02) x.isSyncA()与y.isSyncA() //可以同时访问
    (03) x.cSyncA()与y.cSyncB() //不能同时访问
    (04) x.isSyncA()与Something.cSyncA() //可以同时访问

    每个对象都有一个锁和一个等待队列,类对象也不例外。 synchronized保护的是对象:对实例方法,保护的是当前实例对象this;对静态方法,保护的是类对象。

    synchronized静态方法和synchronized实例方法保护的是不同的对象,不同的两个线程,可以同时,一个执行synchronized静态方法,另一个执行synchronized实例方法。

    任何对象都可以作为锁对象

    2、

    synchronized是可重入的且保证内存可见性:在释放锁时,所有写入都会写回内存,而获得锁后,都会从内存中读最新数据。

    参考资料:

    1、《深入理解Java虚拟机——JVM高级特性与最佳实践》

    2、更多详见 synchronized实现原理

  • 相关阅读:
    table的边框样式(小技巧)
    当人有更高目标追求的话,会发现周围的利益之争很可笑
    科普连载(原著:幽灵蝶)
    关于ASP.NET中的负载均衡
    验证控件与Button的OnClientClick事件(转)
    SQL Server 索引基础知识(2)聚集索引,非聚集索引(转)
    js中的Number和parseInt(小技巧)
    google的一些域名
    对多维宇宙的理解(时间、空间、超越光速,空间时间旅行)
    SNS
  • 原文地址:https://www.cnblogs.com/z-sm/p/6502251.html
Copyright © 2011-2022 走看看