synchronized 关键字

线程

记录一下!
synchronized 的出现作用主要是为了解决线程安全的问题,诱发线程安全主要有以下2点:

  • 存在共享数据(也称为临界资源)
  • 存在多个线程共同操作这些共享数据

解决问题的根本方法: 同一时刻有且只有一个线程在操作共享数据(堆数据),其他线程必须等到该线程处理完后再对共享数据进行操作,此时就引入了【互斥锁】的特性,有如下2点:

  • 互斥性: 即同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程的协调机制,这样在同一时间只有一个线程对需要同步的代码块(复合操作)进行访问,互斥性也称为操作的原子性。
  • 可见性: 必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应该获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作,从而引起不一致。

synchornized 锁的不是代码,锁的都是对象。根据获取的锁的分类,可分为【获取对象锁和获取类锁】

① 获取对象锁的两种用法:

  • 同步代码块: synchronized(this) 或 synchronized(类实例对象),锁是小括号()中的实例对象。
  • 同步非静态方法(synchronized method),锁时当前对象的实例对象。
public class Main { public void foo() throws InterruptedException { System.out.println("233之前"); /** * 多个线程执行到这里就会被锁定,等获取到锁后才会继续执行第二个线程 */ synchronized (this) { Thread.sleep(5000); System.out.println(Thread.currentThread().getName() + ": 233"); } } /** * 作用在方法上,只有该方法执行完毕才会轮到另外的线程执行 * @throws InterruptedException */ public synchronized void bar() throws InterruptedException { System.out.println("方法"); System.out.println(Thread.currentThread().getName() + ": 方法"); Thread.sleep(3000); } public static void main(String[] args) { Main main = new Main(); MyRunnable myRunnable = new MyRunnable(main); Thread thread = new Thread(myRunnable); Thread thread2 = new Thread(myRunnable); Thread thread3 = new Thread(myRunnable); thread.start(); thread2.start(); thread3.start(); } public static class MyRunnable implements Runnable { private Main main; MyRunnable(Main main) { this.main = main; } @Override public void run() { try { main.foo(); main.bar(); } catch (InterruptedException e) { e.printStackTrace(); } } } }

对象锁总结:

  • ①有线程访问对象的同步代码块时,另外的线程可以访问该对象的非同步代码块;
  • ②若锁住的是同一个对象,一个线程在访问对象的同步代码块时,另一个访问对象的同步代码块的线程会被阻塞;
  • ③若锁住的是同一个对象,一个线程在访问对象的同步方法时,另一个访问对象同步方法的线程会被阻塞;
  • ④若锁住的是同一个对象,一个线程在访问对象的同步代码块时,另一个访问对象同步方法的线程会被阻塞,反之亦然;
  • ⑤同一个类的不同对象的对象互不干扰;

类锁的两种用法

  1. 同步代码块(synchronized (类.class)),锁时小括号 () 中的类对象(Class 对象)。
  2. 同步静态方法(synchroized static method),锁时当前对象的类对象( Class 对象)。

类锁总结:

  • ①类锁由于也是一种特殊的对象锁,因此变现和对象锁的1~4一致,而由于一个类只有一把对象锁,所以同一个类的不同对象使用类锁将会是同步的;
  • ②类锁和对象锁互不干扰;

synchronized 底层实现原理

实现 synchronized 的基础

  • Java 对象头

对象在内存中的布局

在 Mark Word 中,重量级锁也就是 synchronized 对象锁

  • Monitor
    c++实现详情
    每个Java对象天生自带了一把看不见的锁,它叫内部锁也叫Monitor锁,Monitor 也叫"管程"或"监视器"锁。

Monitor锁的竞争、获取与释放
Monitor锁的竞争获取与释放.png

文件编译相关命令

  1. 把java文件编译.class文件

javac xxxxx.java

  1. 查看编译后的.class文件

javap -verbose xxxxx.class