synchronized是Java多线程中元老级的锁,也是面试的高频考点,让我们来详细了解synchronized吧。
在Java中,synchronized
锁可能是我们最早接触的锁了,在 JDK1.5之前synchronized是一个重量级锁,相对于juc包中的Lock,synchronized
显得比较笨重。
庆幸的是在 Java 6 之后 Java 官⽅对从 JVM 层⾯对synchronized
进行⼤优化,所以现在的 synchronized 锁效率也优化得很不错。
一、synchronized 使用
1、synchronized的作用
synchronized
的作用主要有三:
- (1)、原子性:所谓原子性就是指一个操作或者多个操作,要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。被
synchronized
修饰的类或对象的所有操作都是原子的,因为在执行操作之前必须先获得类或对象的锁,直到执行完才能释放。 - (2)、可见性:**可见性是指多个线程访问一个资源时,该资源的状态、值信息等对于其他线程都是可见的。 **synchronized和volatile都具有可见性,其中synchronized对一个类或对象加锁时,一个线程如果要访问该类或对象必须先获得它的锁,而这个锁的状态对于其他任何线程都是可见的,并且在释放锁之前会将对变量的修改刷新到共享内存当中,保证资源变量的可见性。
- (3)、有序性:有序性值程序执行的顺序按照代码先后执行。 synchronized和volatile都具有有序性,Java允许编译器和处理器对指令进行重排,但是指令重排并不会影响单线程的顺序,它影响的是多线程并发执行的顺序性。synchronized保证了每个时刻都只有一个线程访问同步代码块,也就确定了线程执行同步代码块是分先后顺序的,保证了有序性。
2、synchronized的使用
Synchronized主要有三种用法:
-
(1)、修饰实例方法: 作用于当前对象实例加锁,进入同步代码前要获得 当前对象实例的锁
复制代码
synchronized void method() { //业务代码 }
-
(2)、修饰静态方法: 也就是给当前类加锁,会作用于类的所有对象实例 ,进入同步代码前要获得 当前 class 的锁。因为静态成员不属于任何一个实例对象,是类成员( static 表明这是该类的一个静态资源,不管 new 了多少个对象,只有一份)。所以,如果一个线程 A 调用一个实例对象的非静态
synchronized
方法,而线程 B 需要调用这个实例对象所属类的静态synchronized
方法,是允许的,不会发生互斥现象,因为访问静态synchronized
方法占用的锁是当前类的锁,而访问非静态synchronized
方法占用的锁是当前实例对象锁。
复制代码
synchronized void staic method() {
//业务代码
}
- (3)、修饰代码块 :指定加锁对象,对给定对象/类加锁。
synchronized(this|obje