码迷,mamicode.com
首页 > 其他好文 > 详细

一篇文章让你读懂synchronized的原理

时间:2019-07-29 21:49:02      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:共享数据   类锁   style   简单的   指令   关键字   exit   存在   额外   

    相信熟悉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的原理

标签:共享数据   类锁   style   简单的   指令   关键字   exit   存在   额外   

原文地址:https://www.cnblogs.com/chalice/p/11265421.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!