本文分以下几点来介绍synchronized(根据JDK1.8)
1. 介绍synchronized
2. synchronized 为什么能保证线程安全
3. synchronized 的 用法
4. synchronized 的锁特性
目录
2.3 synchronized修饰static修饰的静态方法
3. synchronized具体是如何实现线程安全(底层实现)
1. 介绍synchronized
synchronized是解决多线程执行下,访问资源同步性问题的关键字;
我们都知道多线程情况下针对同一个资源进行写访问会导致线程不安全问题;
那么synchronized关键字则是JVM给开发者提供的针对针对指定对象加锁以保证线程安全的关键字
synchronized是依赖监视器锁(monitor)来实现加锁的
在JDK1.6之前,监视器锁(monitor)是直接使用底层操作系统的mutex lock 来实现的,那么每次线程进行加锁解锁操作都得依赖操作系统调度,此时操作系统调度线程是内核态操作,大量的用户态内核态操作切换,则会导致系统资源的浪费,并且内核态操作时间效率也很低下。
所以在JDK1.6之前使用synchronized进行加锁操作,那么这个锁必然是重量级锁,效率较低
从JDK1.6开始,针对synchronized进行了一系列强有力的优化,synchronized加锁不直接依赖使用操作系统底层的互斥锁(mutex lock)来进行加锁的,而是根据一系列情况(锁竞争的强弱等)来升级锁的强度。只有在锁竞争很激烈且线程每次占用锁时间较长的时候才会把锁升级为直接依赖互斥锁的重量级锁。这样很好的提高了线程的并发效率并且大大减少了内核态操作,提高了线程执行效率
大致升级优化过程如下(下篇文章详解):
无锁->偏向锁->轻量级锁->重量级锁
其中包括:偏向锁,锁消除,锁粗化,自旋锁,自适应自旋锁等一系列优化手段,大大提高了锁操作的效率(详情请看下篇文章)
2. synchronized的用法
synchronized的使用得基于某个锁对象进行加锁操作,在一个线程中针对某个锁对象进行加锁后,在该线程没对加锁对象解锁前,其他线程不能使用该锁对象进行加锁操作
举个例子:
public class Test {
//手动指定一个不变得Object对象,专门用于某个synchronized加锁
private static final Object lock = new Object();
public static void showThread (Thread t){
//对锁对象进行加锁
synchronized (lock){
while(true){
System.out.println(t.getName()+"正在执行