锁-synchronized

发布时间 2023-12-11 02:15:06作者: 轻寒

概念:

synchronized是Java的一个关键字,它能够将代码块(方法)锁起来。
synchronized的锁可重入、不可中断、非公平。

优点

它使用起来是非常简单的,只要在代码块(方法)添加关键字synchronized,即可以实现同步的功能。
synchronized是一种互斥锁。
一次只能允许一个线程进入被锁住的代码块。
synchronized是一种内置锁/监视器锁。
Java中每个对象都有一个内置锁(监视器,也可以理解成锁标记),而synchronized就是使用对象的内置锁(监视器)来将代码块(方法)锁定的!

synchronized用处

synchronized保证了线程的原子性(被保护的代码块是一次被执行的,没有任何线程会同时访问)。
synchronized还保证了可见性(当执行完synchronized之后,修改后的变量对其他的线程是可见的)。
Java中的synchronized,通过使用内置锁,来实现对变量的同步操作,进而实现了对变量操作的原子性和其他线程对变量的可见性,从而确保了并发情况下的线程安全。

synchronized的原理

同步代码块:monitorenter和monitorexit指令实现的。
同步方法(在这看不出来需要看JVM底层实现)方法修饰符上的ACC_SYNCHRONIZED实现。
synchronized底层是是通过monitor对象,对象有自己的对象头,存储了很多信息,其中一个信息标示是被哪个线程持有。

重入锁

1.当线程A进入到LoggingWidget的doSomething()方法时,此时拿到了LoggingWidget实例对象的锁。
2.随后在方法上又调用了父类Widget的doSomething()方法,它又是被synchronized修饰。
3.那现在我们LoggingWidget实例对象的锁还没有释放,进入父类Widget的doSomething()方法还需要一把锁吗?
不需要
因为锁的持有者是“线程”,而不是“调用”。线程A已经是有了LoggingWidget实例对象的锁了,当再需要的时候可以继续“开锁”进去这就是内置锁的可重入性。记住,持有锁的是线程。
public class LoggingWidget extends Widget {
   @Override
    public synchronized void doSomething() {
        System.out.println(toString() + ": calling doSomething");
        super.doSomething();
    }
}