同步代码
需要同步的情况
- 当多线程并发,有多段代码同时执行时,希望某一段代码执行的过程中,CPU不要切换到其他线程上,此时就需要同步。
- 如果有两段代码是同步进行的,那么同一时间只能执行其中一段,在一段代码没执行结束之前,不会执行另外一段代码。
同步代码块操作
- 使用 - synchronized关键字加上一个- 锁对象来- 定义一段代码,这就称为- 同步代码块。
- 如果 - 多个同步代码块使用- 同一个锁对象,那么- 他们就是同步的
- 同步代码块是 - 锁机制,同一个锁对象,同步代码块是同步的。
- 锁对象是 - 任意对象,但- 不能是匿名对象,因为匿名对象不是同一个对象。
- 当多个代码块使用了 - 同一个锁对象的- synchronized 锁机制,只有当一个线程把 synchronized 代码块的代码- 全部执行完之后,- 才能去- 执行该同一锁对象的另一段代码。- 即该多个代码块是同步的,同一时间只能执行其中一段,执行完之后,才能执行另一段。
- 若锁对象不一致,即不是同步的,会出现抢占线程执行的情况。
 
- 即该多个代码块是
- 具体操作: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41- 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关键字- 修饰一个方法时,该- 方法中所有代码都是同步的。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- //同步方法只需在方法上加 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- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20- //同步方法只需在方法上加 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,而是产生的字节码对象
 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19- 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();
 }
 }
- 静态域随着类的加载而加载,此时会产生该类的字节码对象,所以
同步方法和同步块,哪个是更好的选择
- 基本原则:同步的范围越小越好。
- 同步块之外的代码是异步执行的,比同步整个方法更有效率。