Synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。
Synchronized的作用主要有三个
1)确保线程互斥的访问同步代码。即保证了一个代码块在同一时间仅有一个线程可以执行。
2)保证共享变量的修改能够及时可见,保证了原子性
3)有效解决重排序问题
怎么使用Synchronized
1)普通同步方法,锁是当前实例对象
public synchronized void method1() {
//TODO
}
2)静态同步方法,锁是当前类的class对象
public static synchronized void method2() {
//TODO
}
3)同步方法块,锁是括号里面的对象
public void method3() {
synchronized(this) {
//TODO
}
}
Synchronize底层原理
参考文章:深入Java虚拟机 第20章,线程同步。Synchronized的语义底层是通过一个monitor的对象来完成
Java中的监视器支持2种线程,互斥和协作。java虚拟机通过对象锁来实现互斥,允许多个线程在同一个共享数据上独立而互不干扰地工作。协作则是通过Object类的wait方法和notify方法来实现,允许多个线程为了同一个目标而共同工作。
每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:
1)如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。
2)如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.
3)如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。
针对同步方法和同步方法块
监视器锁的是当前对象实例
普通方法,其常量池中多了ACC_SYNCHRONIZED标示符。JVM就是根据该标示符来实现方法的同步的:当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象。 其实本质上没有区别,只是方法的同步是一种隐式的方式来实现,无需通过字节码来完成。
针对静态同步方法
监视器锁的是当前对象的Class,跟同步方法法一致,会有进入和退出监视器的流程。