JavaWeb——synchronized详解

目录

一、特性

1、互斥性

2、不可中断性

3、可重入性

二、使用

1、修饰普通方法

2、修饰静态方法

3、修饰代码块

三、锁机制


一、特性

1、互斥性

  • 当线程进入synchronized修饰的代码块时,就相当于加锁。
  • 当线程退出synchronized修饰的代码块时,就相当于解锁。

在同一时刻只允许一个线程持有某个对象的锁,此时只有一个线程使用该代码块。通过这种特性实现了多线程的协调机制。因此互斥性也成为了操作的原子性。

当已经有线程获取到该对象的锁时,其他线程也执行到该对象的被synchronized所修饰的方法也想获取锁进行加锁操作。但由于互斥性无法获取该锁,此时其他线程就会进入阻塞等待状态,直到之前的线程解锁后,其他线程才有机会获得该锁。

注:synchronized是非公平锁,并不会遵守先来后到的规则,而是同时竞争。是否能获得锁还得看操作系统的调度

2、不可中断性

当线程执行到的对象的锁被其他线程获得后,如果当前线程还想获得该锁,就只能进行阻塞等待,直到已获得该锁的线程释放锁后再尝试去获得锁。

3、可重入性

当一个线程请求另一个线程持有的锁时,请求的线程会阻塞,这是synchronized的不可中断性。但当线程去获取自己所拥有的锁时会请求成功而不会阻塞,这就是锁的可重入性

重入的原理:每个锁关联一个计数器和持有者线程,当计数器为0时候,这个锁被认为是没有被任何线程持有。

  • 当有线程持有锁时计数器进行自增并且记下锁的持有线程,当同一线程继续获取锁时计数器继续自增。
  • 当线程退出代码块时相应地计数器减1,直到计数器为0时锁被释放。此时该锁才能被其他线程获得。

同一线程的外层方法获得锁之后,内层方法可以直接获取改锁,可以避免内外层死锁(如下图)。


Object locker=new Object();
 
synchronized(locker){
    synchronized(locker){
 
    }
}

synchronized是可重入锁,可以防止出现死锁

当线程进入了外层的 synchronized 方法时会拿到该锁,加上锁后将会执行代码。而内部又有一个 synchronized修饰的方法,此时也需要获取到同一把锁。想要获取之前的锁就必须要让外层的方法执行完后释放锁,但外层 synchronized 包裹的代码执行完则需要内部的代码先执行完才行。因此该方法无法继续执行,产生了死锁。

此时synchronized 是可重入锁就很好的解决了死锁的问题。

二、使用

1、修饰普通方法

使用synchronized修饰普通方法时,其作用域是整个方法,锁住的对象仅仅是当前对象。

synchronized void func1(){

}

2、修饰静态方法

使用synchronized修饰静态方法时,其作用域时整个静态方法,因为静态方法属于类而不是对象,因此锁住的对象时当前类对象。

synchronized static void func2() {
        
}

3、修饰代码块

使用synchronize修饰代码块时,其作用域是整个代码块,作用对象是括号中的对象,这个作用对象可以是指定的对象,也可以是类。

Object locker=new Object();

synchronized (locker) {

}
  • 在 Java 中,任何一个继承自 Object 类的对象,都可以作为锁对象。加锁操作实际上是在操作 Object 对象头中的一个标识位。
  • 如果括号中的是this,说明锁的对象就是当前对象。
  • 如果括号中的是 xxx.class,说明锁的对象就是类对象。

三、锁机制

synchronized:

  • 既是乐观锁,也是悲观锁。
  • 既是轻量级锁,也是重量级锁。
  • 轻量级锁基于自旋实现,重量级锁基于挂起等待实现。
  • 不是读写锁。
  • 是可重入锁。
  • 是非公平锁。

你可能感兴趣的:(JavaWeb,java,web)