synchronized 的作用?
在 Java 中,synchronized 关键字是用来控制线程同步的,就是在多线程的环 境下,控制 synchronized 代码段不被多个线程同时执行。synchronized 可以 修饰类、方法、变量。
另外,在 Java 早期版本中,synchronized 属于重量级锁,效率低下,因为监视 器锁(monitor)是依赖于底层的操作系统的 Mutex Lock 来实现的,Java 的线 程是映射到操作系统的原生线程之上的。如果要挂起或者唤醒一个线程,都需要 操作系统帮忙完成,而操作系统实现线程之间的切换时需要从用户态转换到内核 态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高,这也是为 什么早期的 synchronized 效率低的原因。庆幸的是在 Java 6 之后 Java 官方 对从 JVM 层面对 synchronized 较大优化,所以现在的 synchronized 锁效率也 优化得很不错了。JDK1.6 对锁的实现引入了大量的优化,如自旋锁、适应性自旋 锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。
d synchronized 关键字最主要的三种使用方式:
• 修饰实例方法: : 作用于当前对象实例加锁,进入同步代码前要获得当前对 象实例的锁
• 修饰静态方法: : 也就是给当前类加锁,会作用于类的所有对象实例,因为 静态成员不属于任何一个实例对象,是类成员( static 表明这是该类的 一个静态资源,不管 new 了多少个对象,只有一份)。所以如果一个线程 A 调用一个实例对象的非静态 synchronized 方法,而线程 B 需要调用这 个实例对象所属类的静态 synchronized 方法,是允许的,不会发生互斥 现象, 因为访问静态 synchronized 方法占用的锁是当前类的锁,而访问 非静态 synchronized 方法占用的锁是当前实例对象锁。
• 修饰代码块: : 指定加锁对象,对给定对象加锁,进入同步代码库前要获得 给定对象的锁。 总结: synchronized 关键字加到 static 静态方法和 synchronized(class)代 码块上都是是给 Class 类上锁。synchronized 关键字加到实例方法上是给对象 实例上锁。尽量不要使用 synchronized(String a) 因为 JVM 中,字符串常量池 具有缓存功能!