zoukankan      html  css  js  c++  java
  • Java内置锁和简单用法

    一、简单的锁知识

    关于内置锁

    Java具有通过synchronized关键字实现的内置锁,内置锁获得锁和释放锁是隐式的,进入synchronized修饰的代码就获得锁,走出相应的代码就释放锁。

    java内置锁是一个互斥锁,这就是意味着最多只有一个线程能够获得该锁,当线程A尝试去获得线程B持有的内置锁时,线程A必须等待或者阻塞,直到线程B释放这个锁,如果B线程不释放这个锁,那么A线程将永远等待下去。

    对象锁和类锁

    这其实也是Java的内置锁。

    对象锁是用于对象实例方法,或者一个对象实例上的,类锁是用于类的静态方法或者一个类的class对象上的。我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象,所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。但是有一点必须注意的是,其实类锁只是一个概念上的东西,并不是真实存在的,它只是用来帮助我们理解锁定实例方法和静态方法的区别的。

    二、synchronized所代表的内置锁的使用方法

    1.synchronized修饰普通方法

    class A {
      public
    synchronized void test() {   }
      public void test2() {

      }
    }

    这种情况下,用的其实是这个方法所在的类的实例对象的锁,也就是A的一个实例的对象锁。意思是,比如A a = new A();,如果两个线程同时调用了a的这个test方法,那么先调用的那个线程,就先拿到这个实例a的对象锁,而另一个线程呢,就要只能等拿到a锁的那个线程运行完这个test方法后,把锁放了,然后再抢到实例a对象锁后才能运行这个test方法。

    注意,虽然说锁的是这个方法所在类的实例对象,但其他线程是可以自由访问这个对象中的非同步方法的。比如这个A类中还有另一个方法叫test2,是不同步的,那么即使线程1抢到对象锁,在进行test方法中,线程2是可以同时访问运行test2方法的,因为这是个不同步的方法。

    2.同步块(对象锁)

    class A {
        public void test() {
            synchronized(this) {//也可以锁其他对象
                xxx
            }
        }
    }

    这个锁的也是某个对象的实例。

    3.类锁(同步块)

    class A {
        public void test() {
            synchronized(A.class) {
                xxx
            }
        }
    }

    其实一鬼样的,就是之前锁的是实例对象,现在锁的是一个类,或者说是一个类对象(Class Object),类锁只是抽象出来的一个概念,而且因为类的Class Object或者说加载的类信息只有一个,所有抽象出来个类锁。

    4.类锁之——修饰static方法

    class A {
        public static synchronized void test() {
            
        }
    }

    synchronized修饰static的方法的时候,也是类锁,锁的也是这个类,或者说是这个类的Class Object,因为静态方法是所有对象实例共有的,一个类只有一个,static方法也是在类加载的时候就加载了,所以synchronized修饰static方法的时候,锁也是唯一的,所以也是类锁哦。

    三、关于类锁和对象锁的注意:

    看下这个例子:

    public class TestSynchronized 
    {  
        public synchronized void test1() 
        {  
                  int i = 5;  
                  while( i-- > 0) 
                  {  
                       System.out.println(Thread.currentThread().getName() + " : " + i);  
                       try 
                       {  
                            Thread.sleep(500);  
                       } 
                       catch (InterruptedException ie) 
                       {  
                       }  
                  }  
        }  
        public static synchronized void test2() 
        {  
             int i = 5;  
             while( i-- > 0) 
             {  
                  System.out.println(Thread.currentThread().getName() + " : " + i);  
                  try 
                  {  
                       Thread.sleep(500);  
                  } 
                  catch (InterruptedException ie) 
                  {  
                  }  
             }  
        }  
        public static void main(String[] args) 
        {  
             final TestSynchronized myt2 = new TestSynchronized();  
             Thread test1 = new Thread(  new Runnable() {  public void run() {  myt2.test1();  }  }, "test1"  );  
             Thread test2 = new Thread(  new Runnable() {  public void run() { TestSynchronized.test2();   }  }, "test2"  );  
             test1.start();  
             test2.start();  
    //         TestRunnable tr=new TestRunnable();
    //         Thread test3=new Thread(tr);
    //         test3.start();
        } 
    }
     
    
    test1 : 4
    test2 : 4
    test1 : 3
    test2 : 3
    test2 : 2
    test1 : 2
    test2 : 1
    test1 : 1
    test1 : 0
    test2 : 0

    上面代码synchronized同时修饰静态方法和实例方法,但是运行结果是交替进行的,这证明了类锁和对象锁是两个不一样的锁,控制着不同的区域,它们是互不干扰的。同样,线程获得对象锁的同时,也可以获得该类锁,即同时获得两个锁,这是允许的。

    其实这个也很显然,一个锁的是类的实例,一个是类的Class Object,这两个都不是一个东西hh。

    四、synchronized中条件判断用while而不是用if

    例子见这篇文章:https://www.cnblogs.com/heyboom/p/9147469.html

  • 相关阅读:
    显示文件本地文件夹
    Select Dependencies选择依赖项
    搜索小技巧
    783. Minimum Distance Between BST Nodes BST节点之间的最小距离
    5. Longest Palindromic Substring 最长的回文子串
    12. Integer to Roman 整数转罗马数字
    3. Longest Substring Without Repeating Characters 最长的子串不重复字符
    539. Minimum Time Difference 最小时差
    43. Multiply Strings 字符串相乘
    445. Add Two Numbers II 两个数字相加2
  • 原文地址:https://www.cnblogs.com/wangshen31/p/10432363.html
Copyright © 2011-2022 走看看