zoukankan      html  css  js  c++  java
  • Java 类锁、对象锁、私有锁

    3.6 Java类锁、对象锁、私有锁、隐式锁


    类锁对象锁是否会冲突?对象锁和私有锁是否会冲突?通过实例来进行说明。

    一、相关约定

    为了明确后文的描述,先对本文涉及到的锁的相关定义作如下约定:

    1. 类锁:在代码中的方法上加了static和synchronized的锁,或者synchronized(xxx.class)的代码段,如下文中的increament();

    2.对象锁:在代码中的方法上加了synchronized的锁,或者synchronized(this)的代码段,如下文中的synOnMethod()和synInMethod();

    3.私有锁:在类内部声明一个私有属性如private Object lock,在需要加锁的代码段synchronized(lock),如下文中的synMethodWithObj()。

    二、测试代码

    1.编写一个启动类ObjectLock

    1. public class ObjectLock {
    2.     public static void main(String[] args) {
    3.         System.out.println("start time = " + System.currentTimeMillis()+"ms");
    4.         LockTestClass test = new LockTestClass();
    5.         for (int i = 0; i < 3; i++) {
    6.             Thread thread = new ObjThread(test, i);
    7.             thread.start();
    8.         }
    9.     }
    10. }

      2.编写一个线程类ObjThread,用于启动同步方法(注意它的run方法可能会调整以进行不同的测试)

      1. public class ObjThread extends Thread {
      2.     LockTestClass lock;
      3.     int i = 0;
      4.  
      5.     public ObjThread(LockTestClass lock, int i) {
      6.         this.lock = lock;
      7.         this.= i;
      8.     }
      9.  
      10.     public void run() {
      11.         //无锁方法
      12. //      lock.noSynMethod(this.getId(),this);
      13.         //对象锁方法1,采用synchronized synInMethod的方式
      14.         lock.synInMethod();
      15.         //对象锁方法2,采用synchronized(this)的方式
      16. //      lock.synOnMethod();
      17.         //私有锁方法,采用synchronized(object)的方式
      18. //      lock.synMethodWithObj();
      19.         //类锁方法,采用static synchronized increment的方式
      20.         LockTestClass.increment();
      21.     }
      22. }

        3.再编写一个锁的测试类LockTestClass,包括各种加锁方法

        1. public class LockTestClass {
        2.     //用于类锁计数
        3.     private static int i = 0;
        4.     //私有锁
        5.     private Object object = new Object();
        6.  
        7.     /**
        8.      * &lt;p&gt;
        9.      * 无锁方法
        10.      *
        11.      * @param threadID
        12.      * @param thread
        13.      */
        14.     public void noSynMethod(long threadID, ObjThread thread) {
        15.         System.out.println("nosyn: class obj is " + thread + ", threadId is"
        16.                 + threadID);
        17.     }
        18.  
        19.     /**
        20.      * 对象锁方法1
        21.      */
        22.     public synchronized void synOnMethod() {
        23.         System.out.println("synOnMethod begins" + ", time = "
        24.                 + System.currentTimeMillis() + "ms");
        25.         try {
        26.             Thread.sleep(2000L);
        27.         } catch (InterruptedException e) {
        28.             e.printStackTrace();
        29.         }
        30.         System.out.println("synOnMethod ends");
        31.     }
        32.  
        33.     /**
        34.      * 对象锁方法2,采用synchronized (this)来加锁
        35.      */
        36.     public void synInMethod() {
        37.         synchronized (this) {
        38.             System.out.println("synInMethod begins" + ", time = "
        39.                     + System.currentTimeMillis() + "ms");
        40.             try {
        41.                 Thread.sleep(2000L);
        42.             } catch (InterruptedException e) {
        43.                 e.printStackTrace();
        44.             }
        45.             System.out.println("synInMethod ends");
        46.         }
        47.  
        48.     }
        49.  
        50.     /**
        51.      * 对象锁方法3
        52.      */
        53.     public void synMethodWithObj() {
        54.         synchronized (object) {
        55.             System.out.println("synMethodWithObj begins" + ", time = "
        56.                     + System.currentTimeMillis() + "ms");
        57.             try {
        58.                 Thread.sleep(2000L);
        59.             } catch (InterruptedException e) {
        60.                 e.printStackTrace();
        61.             }
        62.             System.out.println("synMethodWithObj ends");
        63.         }
        64.     }
        65.  
        66.     /**
        67.      * 类锁
        68.      */
        69.     public static synchronized void increament() {
        70.         System.out.println("class synchronized. i = " + i + ", time = "
        71.                 + System.currentTimeMillis() + "ms");
        72.         i++;
        73.         try {
        74.             Thread.sleep(2000L);
        75.         } catch (InterruptedException e) {
        76.             e.printStackTrace();
        77.         }
        78.          System.out.println("class synchronized ends.");
        79.     }
        80.  
        81. }

          三、测试结果

          1. 测试类锁和对象锁,ObjectThread的run方法修改如下:

          1. public void run() {
          2.         //无锁方法
          3. //      lock.noSynMethod(this.getId(),this);
          4.         //对象锁方法1,采用synchronized synInMethod的方式
          5.         lock.synInMethod();
          6.         //对象锁方法2,采用synchronized(this)的方式
          7. //      lock.synOnMethod();
          8.         //私有锁方法,采用synchronized(object)的方式
          9. //      lock.synMethodWithObj();
          10.         //类锁方法,采用static synchronized increment的方式
          11.         LockTestClass.increament();
          12.     }

            终端输出:

            1. start time = 1413101360231ms
            2.  synInMethod begins, time = 1413101360233ms
            3.  synInMethod ends
            4.  class synchronized. i = 0, time = 1413101362233ms
            5.  synInMethod begins, time = 1413101362233ms 
            6.  class synchronized ends. 
            7.  synInMethod ends 
            8.  class synchronized. i = 1, time = 1413101364233ms 
            9.  synInMethod begins, time = 1413101364233ms 
            10.  class synchronized ends. 
            11.  synInMethod ends 
            12.  class synchronized. i = 2, time = 1413101366234ms 
            13.  class synchronized ends.

              可以看到对象锁方法(synInMothod)第一次启动时比类锁方法(increament)快2秒,这是因为在synInMehtod执行时 sleep了2秒再执行的increament,而这两个方法共用一个线程,所以会慢2秒,如果increament在run中放到 synInMethod前面,那么第一次启动时就是increament快2秒。

              而当类锁方法启动时,另一个线程时的对象锁方法也几乎同时启动,说明二者使用的并非同一个锁,不会产生竞争。

              结论:类锁和对象锁不会产生竞争,二者的加锁方法不会相互影响。

              2.私有锁和对象锁,ObjectThread的run方法修改如下:

              1. public void run() {
              2.         //无锁方法
              3. //      lock.noSynMethod(this.getId(),this);
              4.         //对象锁方法1,采用synchronized synInMethod的方式
              5.         lock.synInMethod();
              6.         //对象锁方法2,采用synchronized(this)的方式
              7. //      lock.synOnMethod();
              8.         //私有锁方法,采用synchronized(object)的方式
              9.         lock.synMethodWithObj();
              10.         //类锁方法,采用static synchronized increment的方式
              11. //      LockTestClass.increament();
              12.     }

                终端输出:

                1. start time = 1413121912406ms 
                2. synInMethod begins, time = 1413121912407ms. 
                3. synInMethod ends. 
                4. synMethodWithObj begins, time = 1413121914407ms 
                5. synInMethod begins, time = 1413121914407ms. 
                6. synInMethod ends. 
                7. synMethodWithObj ends 
                8. synInMethod begins, time = 1413121916407ms. 
                9. synMethodWithObj begins, time = 1413121916407ms 
                10. synInMethod ends. 
                11. synMethodWithObj ends 
                12. synMethodWithObj begins, time = 1413121918407ms 
                13. synMethodWithObj ends

                  和类锁和对象锁非常类似。

                  结论:私有锁和对象锁也不会产生竞争,二者的加锁方法不会相互影响。

                  3.synchronized直接加在方法上和synchronized(this),ObjectThread的run方法修改如下:

                  1. public void run() { 
                  2. //无锁方法 // lock.noSynMethod(this.getId(),this); 
                  3. //对象锁方法1,采用synchronized synInMethod的方式 
                  4. lock.synInMethod(); 
                  5. //对象锁方法2,采用synchronized(this)的方式 
                  6. lock.synOnMethod(); 
                  7. //私有锁方法,采用synchronized(object)的方式 
                  8. // lock.synMethodWithObj(); 
                  9. //类锁方法,采用static synchronized increment的方式 
                  10. // LockTestClass.increament(); 
                  11. }

                    终端输出:

                    1. start time = 1413102913278ms 
                    2. synInMethod begins, time = 1413102913279ms 
                    3. synInMethod ends 
                    4. synInMethod begins, time = 1413102915279ms 
                    5. synInMethod ends 
                    6. synOnMethod begins, time = 1413102917279ms 
                    7. synOnMethod ends 
                    8. synInMethod begins, time = 1413102919279ms 
                    9. synInMethod ends 
                    10. synOnMethod begins, time = 1413102921279ms 
                    11. synOnMethod ends 
                    12. synOnMethod begins, time = 1413102923279ms 
                    13. synOnMethod ends

                       可以看到,二者严格地串行输出(当然再次执行时先运行synInMethod还是先运行synOnMethod并不是确定的,取决于谁获得了锁)。 

                      结论:synchronized直接加在方法上和synchronized(this)都是对当前对象加锁,二者的加锁方法够成了竞争关系,同一时刻只能有一个方法能执行。   


                    • 相关阅读:
                      一sqlite分页 语句,
                      array调用排序,返回的数组要 重新赋值,
                      sublime text3快速编辑选中多行
                      sublime text3实现多行快速编辑Ctrl+E或者Tab
                      sublime使用Markdown Preview标记语言
                      解决sublime package control 出现There are no packages available for installation
                      sublime text 3安装html-css-js prettify后使用时报错An unhandled OS error was encountered
                      sublime格式化插件---HTML-CSS-JS Prettify美化代码
                      node=day5
                      封装异步API
                    • 原文地址:https://www.cnblogs.com/jpfss/p/10027315.html
                    Copyright © 2011-2022 走看看