RSA 優化 的原理詳解 ,synchronized的使用

一、 原來代碼

  • 示例代碼:

       private static org.bouncycastle.jce.provider.BouncyCastleProvider bouncyCastleProvider = null;
       public static  org.bouncycastle.jce.provider.BouncyCastleProvider getBouncyCastleProviderInstance() {
           if (bouncyCastleProvider == null) {
               bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
           }
           return bouncyCastleProvider;
       }
    

二、 優化後代碼

  • 示例代碼:

      private static  volatile org.bouncycastle.jce.provider.BouncyCastleProvider bouncyCastleProvider ;
      public static  org.bouncycastle.jce.provider.BouncyCastleProvider getBouncyCastleProviderInstance() {
          if (bouncyCastleProvider == null) {
              synchronized(org.bouncycastle.jce.provider.BouncyCastleProvider.class){
                  if(bouncyCastleProvider == null){
                      bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
                  }
              }
          }
          return bouncyCastleProvider;
      }
    

三、實現原理

  • 添加synchronized關鍵字。添加到同步代碼塊中,而不是如下:

    public static synchronized org.bouncycastle.jce.provider.BouncyCastleProvider getBouncyCastleProviderInstance() {
        if (bouncyCastleProvider == null) {
            bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
        }
        return bouncyCastleProvider;
     }
    
  • 目的:即:保證在同一時刻最多隻有一個線程執行該段代碼,達到保證併發安全的效果。

四 、 synchronized

  • 定義

    • synchronized鎖是重量級鎖,重量級體現在活躍性差一點。synchronized鎖是內置鎖,意味着JVM能基於synchronized鎖做一些優化:比如增加鎖的粒度(鎖粗化)、鎖消除。
    • synchronized鎖釋放是自動的,當線程執行退出synchronized鎖保護的同步代碼塊時,會自動釋放synchronized鎖。
    • 線程在競爭synchronized鎖時是非公平的。
  • synchronized Java中的關鍵字,是一種同步鎖。它修飾的對象有以下幾種:

    1. 修飾一個代碼塊,被修飾的代碼塊稱爲同步語句塊,其作用的範圍是大括號{}括起來的代碼,作用的對象是調用這個代碼塊的對象;
    2. 修飾一個方法,被修飾的方法稱爲同步方法,其作用的範圍是整個方法,作用的對象是調用這個方法的對象;
    3. 修飾一個靜態的方法,其作用的範圍是整個靜態方法,作用的對象是這個類的所有對象;
    4. 修飾一個類,其作用的範圍是synchronized後面括號括起來的部分,作用主的對象是這個類的所有對象。
  • 使用

    • 1、 普通同步方法,鎖的是當前實例的對象

      • 同步方法鎖住的是調用方法的對象;新創建的對象調用方法,和之前的方法不同步。
         class mYread implements Runnable {
            private static int count;
            public mYread() {
               count = 0;
            }
            public synchronized  void method() {
               for (int i = 0; i < 5; i ++) {
                  try {
                     System.out.println(Thread.currentThread().getName() + ":" + (count++));
                     Thread.sleep(100);
                  } catch (InterruptedException e) {
                     e.printStackTrace();
                  }
               }
            }
            public synchronized void run() {
               method();
            }
         }
         //執行調用
          mYread read1 = new mYread();
          mYread read2 = new mYread();
          Thread thread1 = new Thread(read1, "mYread1");
          Thread thread2 = new Thread(read2, "mYread2");
          thread1.start();
          thread2.start();
          
          read1 和 read2 是兩個對象,thread1和thread2執行不會保持線程同步。
       ```
    -  2、 靜態同步方法,鎖的是靜態方法所在的類對象
      
      - 靜態同步方法鎖的是類的對象,新創建的對象也是被鎖的對象。
    
    
     class mYread implements Runnable {
        private static int count;
        public mYread() {
           count = 0;
        }
        public synchronized static void method() {
           for (int i = 0; i < 5; i ++) {
              try {
                 System.out.println(Thread.currentThread().getName() + ":" + (count++));
                 Thread.sleep(100);
              } catch (InterruptedException e) {
                 e.printStackTrace();
              }
           }
        }
        public synchronized void run() {
           method();
        }
     }
     //執行調用
      mYread read1 = new mYread();
      mYread read2 = new mYread();
      Thread thread1 = new Thread(read1, "mYread1");
      Thread thread2 = new Thread(read2, "mYread2");
      thread1.start();
      thread2.start();
      
      read1 和 read2 是兩個對象,但在thread1和thread2併發執行時卻保持了線程同步。
     ```
    
    • 3、 同步代碼塊,鎖的是括號裏的對象。(此處的可以是實例對象,也可以是類的class對象。)
    1. 指定給某個對象加鎖

      如果有一個明確的對象:

        public abstract class RSACoderUtils extends CoderUtils {
           if (bouncyCastleProvider == null) { 
               synchronized(org.bouncycastle.jce.provider.BouncyCastleProvider.class){
                   if(bouncyCastleProvider == null){
                       bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
                   }
               }
           }
        }
      

      如果沒有一個明確的對象:

         public abstract class RSACoderUtils extends CoderUtils {
            if (bouncyCastleProvider == null) { 
                private byte[] lock = new byte[0];  // 特殊的instance變量         
                synchronized(lock){
                       if(bouncyCastleProvider == null){
                           bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
                       }
                 }
            }
         }            
      

      -. 比較兩種創建對象的消耗:

           Object lock = new Object();
           private byte[] lock = new byte[0];
      

      通過查看編譯後的字節碼:生成零長度的byte[]的lock需要3行操作碼,Object 的lock 則需要7行操作碼,故零長度的byte數組對象創建性能更好。

    2. 給某個類加鎖

           public abstract class RSACoderUtils extends CoderUtils {
              public void test(){
                  synchronized(RSACoderUtils.class){
                      if(bouncyCastleProvider == null){
                          bouncyCastleProvider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
                      }
                  }
              }
           }
      

五、volatile

  • 禁止指令重排序優化
  • 保證此變量對所有線程的可 見性,這裏的“可見性”是指當一條線程修改了這個變量的值,新值對於其他線程來說是可以 立即得知的。

六、 單例模式

  • 保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。
  • 懶漢模式 :
	public class Monitor {
		   private static Monitor monitor = null;
		   private static volatile Monitor monitor = null;   //
		       private Monitor() {}
			public static Monitor getMonitor() {
				   if (monitor == null) {
					       synchronized (Monitor.class) {
					           if (monitor == null) {
					               monitor = new Monitor();
					           } 
					       }
				   }
				   return monitor;
			}
}
  • 餓漢模式:
 public class Monitor {
        private static Monitor monitor = new Monitor ();
        private  Monitor () {}
        public static Monitor getMonitor() {
            return monitor;
        }
 }

更多內容,阿里博客地址:
https://yq.aliyun.com/users/article?spm=a2c4e.11153940.headeruserinfo.3.2b9f291a9z4pJ7
歡迎關注公衆號,查看更多內容 :
volatile 關鍵字的詳細介紹;
synchronized 關鍵字的詳解;
XG54_9_WXMH_5X_HB_H_7V

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章