zoukankan      html  css  js  c++  java
  • Synchronize原理

    1 普通方法上

    2 静态方法上

     修饰静态方法内置锁是当前的Class字节码对象

     修饰普通方法内置锁是当前类的实例

    原理与使用:

       从字节码层面解释:

         执行同步代码块

         monitorenter 

         synchronized( ){

         }

       monitorexit  

    任何对象都可以作为锁,那么锁信息有存在对象的什么地方呢? 

       存在对象头中

    对象头中的信息    Mark Word   Class Metadata Address   ArrayLength

    Mark Word 存储的是哈希值 锁信息  空间利用率很高的

    任何对象都可以作为锁,那么锁信息又存在对象的什么地方呢? 

       存在对象头中

          对象头中的信息: Mark Word             Class MetaData Address    

          

    jdk1.6之后 引入了

    偏向锁:  每次获取锁和释放锁会浪费资源。很多情况下,竞争者不是由多个线程,而是由一个线程在使用。

                     

      当一个线程进来时候,找对象头查看是否是偏向锁。偏向锁的Mark Word  字段会记录一些信息 :线程id    Epoch  对象分代年龄信息  是否是偏向锁    锁标志位  

      检查锁标志位是否是偏向锁,接着会检查线程的id如果和当前线程id是一致(第一次直接进来)。第二次进来时候 接着运行同步代码块(没有锁的获取和释放)。偏向锁获取时候,没有撤销。等到有竞争时候 才有释放的机制。  场景:只有一个线程访问代码块会大大提高性能。(多个线程会降低性能)

    轻量级锁:

        首先栈帧

          虚拟机栈里面存储的是一个个栈帧,每个方法执行都会存储一个栈帧。每个方法执行都会执行栈帧的进栈出栈。

          复制Mark Word 到虚拟机栈中

          竞争成功之后会将锁的标志位改成轻量级锁,然后执行同步体。  

         其他线程也是复制Mark Word到虚拟机中

          修改Mark Word,发现已经被别的线程获得了锁,所以修改不成功。然后不停的修改。直到第一个线程把锁释放了才OK

          第一个线程执行完毕,第二个获取锁之后,会升级为重量级锁(普遍意义上的synchronize),线程会阻塞。 
          

         轻量级锁用到了自旋概念。好处:多个线程可以同时

         

    关于单例模式结合Synchronize

          单例模式与线程安全问题

             饿汉式是没有线程安全问题的

             懒汉式是有线程安全问题的

        缩小同步代码块的范围,只有在创建时候才有写的操作 其他的都是读的操作没有线程安全问题

         在会出现线程安全问题地方加一个synchronize,锁当前的代码 包裹起来

         这样其实还是有问题的,双重加锁,再来一个验空。

         这样视乎是一个没有问题,重排序问题。

         有可能先执行下面的 在执行上面的这样的重排序问题(没法演示)

         

       

    package com.toov5.threadTest;
    public class DoubleLock {
    
        private static volatile DoubleLock doubleLock;   //防止重排序
        
        private DoubleLock(){
            
        }
        public static DoubleLock getInstance(){  //比较饿汉模式而言的,如果在这一行加锁,效率势必会比较低  利用同步代码块
            //自旋while(true)
            if (doubleLock == null){   //判断一下  如果为null时候  这种情况下才会去创建对象
                synchronized (DoubleLock.class){ //静态的用 字节码文件    
                    if (doubleLock==null) {  //上锁完了之后 可能没有创建完毕 所以要判断一下  但是 重排序时候 可能会导致 对象可能创建多次
                                             //所以加volitile关键字 (单线程是不会产生重排序问题)
                        doubleLock=new DoubleLock();
                    }
                }
    
            }
            return doubleLock;   //不为空的话 会直接返回呀  多个线程去创建时候 才有有安全塞问题
        }
        
        
        
        public static void main(String[] args) {
             DoubleLock doubleLock1 = DoubleLock.getInstance();
             DoubleLock doubleLock2 = DoubleLock.getInstance();
             System.out.println(doubleLock1==doubleLock2);
        }
        
    }

       

  • 相关阅读:
    Python中Linux开发的常识
    Python GUI编程(Tkinter)
    linux文本编辑器教学
    WordCloud安装
    怎么安装wordcloud
    java内功 ---- jvm虚拟机原理总结,侧重于GC
    spring源码分析(二)Aop
    spring源码分析(一)IoC、DI
    java内部类技术提炼
    java自定义注解实现前后台参数校验
  • 原文地址:https://www.cnblogs.com/toov5/p/10454371.html
Copyright © 2011-2022 走看看