Java多线程回顾-同步代码

同步代码

需要同步的情况

  • 多线程并发,有多段代码同时执行时,希望某一段代码执行的过程中CPU不要切换到其他线程上,此时就需要同步。
  • 如果有两段代码是同步进行的,那么同一时间只能执行其中一段,在一段代码没执行结束之前不会执行另外一段代码。

同步代码块操作

  • 使用synchronized关键字加上一个锁对象定义一段代码,这就称为同步代码块

  • 如果多个同步代码块使用同一个锁对象,那么他们就是同步的

  • 同步代码块是锁机制,同一个锁对象,同步代码块是同步的。

  • 锁对象是任意对象,但不能是匿名对象,因为匿名对象不是同一个对象。

  • 当多个代码块使用了同一个锁对象synchronized 锁机制,只有当一个线程把 synchronized 代码块的代码全部执行完之后才能执行该同一锁对象的另一段代码

    • 即该多个代码块是同步的,同一时间只能执行其中一段,执行完之后,才能执行另一段。
    • 锁对象不一致,即不是同步的,会出现抢占线程执行的情况。
  • 具体操作:

    public class SynchronizeTest {
      public static void main(String[] args) {
          Consumer con  = new Consumer();
          new Thread(()->{
              while(true)
                  con.print1();
          }).start();
    
          new Thread(()->{
              while(true)
                  con.print2();
          }).start();
      }
    }
    
    class Consumer {
      //定义一个Object对象,作为锁对象
      Object  obj = new Object();
    
      public void print1(){
          //锁机制使用同一个锁对象
          synchronized (obj){
              System.out.print("同");
              System.out.print("步");
              System.out.print("代");
              System.out.print("码");
              System.out.print("块");
              System.out.println();
          }
      }
    
      public void  print2(){
          //锁机制使用同一个锁对象,作为同步代码块
          synchronized(obj){
              System.out.print("多");
              System.out.print("线");
              System.out.print("程");
              System.out.println();
          }
      }
    }
    

同步方法

  • 使用synchronized关键字修饰一个方法时,该方法中所有代码都是同步的。

    //同步方法只需在方法上加 synchronized 
    public synchronized void print1(){
      //锁机制使用同一个锁对象
      synchronized (obj){
          System.out.print("同");
          System.out.print("步");
          System.out.print("代");
          System.out.print("码");
          System.out.print("块");
          System.out.println();
      }
    }
  • 非静态同步函数的锁是this

    //同步方法只需在方法上加 synchronized 
    public synchronized void print1(){
    
          System.out.print("同");
          System.out.print("步");
          System.out.print("代");
          System.out.print("码");
          System.out.print("块");
          System.out.println();
    
    }
    public void  print2(){
      //非静态的同步方法的锁对象是this
      synchronized(this){
          System.out.print("多");
          System.out.print("线");
          System.out.print("程");
          System.out.println();
      }
    }
    

    此时 这两个方法时 同步的

  • 静态同步函数的锁是字节码对象

    • 静态域随着类的加载而加载,此时会产生该类的字节码对象,所以静态同步方法锁对象不能是this,而是产生的字节码对象
    public static synchronized void print1(){
    
          System.out.print("同");
          System.out.print("步");
          System.out.print("代");
          System.out.print("码");
          System.out.print("块");
          System.out.println();
    
    }
    public static void  print2(){
      //静态的同步方法的锁对象是随着类加载而产生的类的字节码对象
      synchronized(Customer.class){
          System.out.print("多");
          System.out.print("线");
          System.out.print("程");
          System.out.println();
      }
    }
    

同步方法和同步块,哪个是更好的选择

  • 基本原则:同步的范围越小越好
  • 同步块之外的代码是异步执行的,比同步整个方法更有效率。

猜你喜欢

转载自blog.csdn.net/hxhaaj/article/details/81004839