首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >synchronized 关键字

synchronized 关键字

作者头像
happyJared
发布2019-07-03 16:36:55
4180
发布2019-07-03 16:36:55
举报
文章被收录于专栏:happyJaredhappyJared

synchronized 关键字解决的是多个线程间访问同一资源的同步性问题。

早期版本中,synchronized 属于重量级锁,效率低下,这是由于监视器锁(monitor)是依赖于底层操作系统的 Mutex Lock 来实现的,Java 的线程是映射到操作系统的原生线程之上。如果要挂起或者唤醒线程,都需要操作系统帮忙完成,而操作系统进行线程间的切换时,需要从用户态转换到内核态,这个状态的转换需要相对长的时间,时间成本较高,这也就是早期 synchronized 效率低下的主要原因。庆幸的是,Java1.6 以后官方对 synchronized 做了较大的优化,因此现在的 synchronized 锁效率也是比较高的(推荐先使用)。

synchronized 关键字最主要的三种使用方式:

  1. 修饰实例方法: 给当前对象实例加锁,进入同步代码前要获得当前对象实例的锁;
  2. 修饰静态方法: 也就是给当前类加锁,会作用于类的所有对象实例,因为静态成员不属于任何一个实例对象,(static 修饰表明是类成员,是该类的一个静态资源,所以不管 new 了多少个对象,应有中也只有一份)。如果一个线程 A 调用一个实例对象的非静态 synchronized 方法,而线程 B 调用这个实例对象所属的类的静态 synchronized 方法,这是允许的,不会发生互斥现象,因为访问静态 synchronized 方法占用的锁是当前类的锁,而访问非静态 synchronized 方法占用的锁是当前实例对象的锁;
  3. 修饰代码块: 指定加锁对象,对给定对象加锁,进入同步代码块前要获得给定对象的锁。

synchronized 关键字加到 static 静态方法和 synchronized(class) 代码块上都是对当前 Class 类上锁; synchronized 关键字加到实例方法上是给对象实例上锁; 尽量不要使用 synchronized(String s),因为 JVM 中,字符串常量池具有缓存功能。

  • 代码示例:双重校验锁(DCL)实现的对象单例(线程安全)
public class Singleton {

    // DCL 方式的单例需确保使用 volatile 
    private volatile static Singleton uniqueInstance;

    // 私有化构造器
    private Singleton() {
    }

    public static Singleton getUniqueInstance() {
       // 先判断对象是否已经实例过,没有实例化过才进入加锁代码
        if (uniqueInstance == null) {
            //类对象加锁
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }

}

使用 volatile 关键字可以禁止 JVM 的指令重排,保证多线程环境下代码也能正常执行.。

以上 uniqueInstance = new Singleton(); 这段代码其实是分为三步执行:

  1. 为 uniqueInstance 分配内存空间
  2. 初始化 uniqueInstance
  3. 将 uniqueInstance 指向分配的内存地址

由于 JVM 具有指令重排的特性,所以上述执行顺序有可能变成 1->3->2,指令重排在单线程环境下不会有问题,但多线程下会导致线程可能得到还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用 getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance,但此时 uniqueInstance 还未被初始化。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.07.03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档