让你读懂synchronized的原理

Posted chalice

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了让你读懂synchronized的原理相关的知识,希望对你有一定的参考价值。

    相信熟悉java的同学对synchronized关键字也是非常熟悉了,似乎只要在涉及到线程安全的问题的问题中,加上synchronized关键字就对了!

  比如下面这个我们比较常见的代码,懒汉式单例模式:

public class LazySimpleSinglethon 
    private static LazySimpleSinglethon singlethon = null;

    private LazySimpleSinglethon()

    public synchronized tatic LazySimpleSinglethon getInstance()
        if(singlethon==null) //如果不加synchronizde会存在线程安全问题
            singlethon = new LazySimpleSinglethon();
        

        return singlethon;
    

          好,问题来了,为什么会有线程安全问题?什么是线程安全问题?《Java Concurrency In Practice》一书的作者Brian Goetz 对“线程安全“有一个比较恰到的定义:“当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象就是线程安全的。” 看完这一段定义,我们可以理解为,当我们在编写代码的时候不需要考虑线程问题即不加上同步处理,程序的运行结果仍然会是正常的,那我们可以说这是线程安全的。比如上面这段代码,如果我们不加上synchronized关键字,那么在多线程环境下,很有可能会创建多个单例对象,很显然这不是我们想要的,也违背了单例模式的设计原则。

  线程安全问题,说白了就是多个线程在操作共享数据时引发的数据安全问题。

 

  在java语言中,使用synchronized关键字是我们使用互斥同步的方式(还有其他的方式保证线程安全,日后再聊)来保证线程安全的常用手段,那是不是只要涉及线程安全问题,我们都可以用synchronize来解决呢?使用synchronized关键字会不会对性能有什么影响?使用synchronized关键字的缺陷又在哪里呢?接下来我们就好好的聊一聊,synchronized关键字。

  

  •    synchrozized的用法:
  1. 修饰实例方法,作用于当前实例加锁,进入同步代码块前要获得当前实例的锁。
  2. 修饰静态方法,作用于当前类加锁,进入同步代码前要获得当前类对象的锁。
  3. 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码块前要获得给定对象的锁。

  简单的示例代码:

public class SyncDemo 

    //修饰实例方法
   public synchronized void syncMethod() //对象锁

   

   public void syncCode()
       //修饰代码块
       synchronized (this)   //  括号表示作用范围  this是对象级别  SyncDemo.class类级别
           //保护存在线程安全的变量
       
   
    //修饰静态方法
   public synchronized static void syncStaticMethod()  //类锁
        //TODO
   

   以上代码表示synchronized关键字的两种作用范围,一种作用于对象,一种作用于类。观察synchronized 的整个语法发现,synchronized(lock)是基于lock 这个对象的生命周期来控制锁粒度的,如果这个对象是类,那么作用范围是类级别,如果是对象,那么作用范围就是对象。显而易见类级别的范围要大于对象级别(类的生命周期>对象的生命周期),锁的级别越小,对程序性能的影响也越小。

 

 

  synchronized 关键字经过编译之后,会在同步块的前后分别形成monitorenter和monitorexit这两个字节码指令,这两个字节码都需要- 个reference类型的参数来指明要锁定和解锁的对象。如果Java程序中的synchronized明确指定了对象参数,那就是这个对象的reference ;如果没有明确指定,那就根据synchronized修饰的是实例方法还是类方法,去取对应的对象实例或Class对象来作为锁对象。

 

以上是关于让你读懂synchronized的原理的主要内容,如果未能解决你的问题,请参考以下文章

让你读懂 OpenStack 的起源架构和应用

一文让你读懂“反射机制”!

一篇文章让你读懂Spring事务管理器

这篇文章让你读懂元数据及其意义

一文让你读懂网站HTTPS证书是什么

就这?一篇文章让你读懂 Spring 事务