synchronized是java里面的关键字
synchronized 方法为防止线程干扰和内存一致性错误提供了一个简单的策略:如果一个对象对多个线程可见,则通过同步方法完成对该对象变量的所有读取或写入操作。
简而言之,当你有两个线程正在读写相同的'资源'时,比如说一个名为变量的变量foo,你需要确保这些线程以同步的方式访问变量。如果没有synchronized关键字,线程1可能看不到更改线程2 foo,或者更糟糕的是,它可能只有一半被更改。这不会是你所期望的。
synchronized修饰的方法或者代码块只要前一个线程的执行没有完成,就阻塞下一个线程对方法该方法的调用。线程一次可以访问这个方法。如果没有synchronized全部线程可以同时访问这个方法
synchronized可以加在代码块上,方法上,静态代码块上
加在代码块上需要一个对象作为锁对象,作用范围是被包围的代码块,在代码块之外的代码是可以正常运行的(如果当前锁对象是当前类的class的话,那么和静态方法加锁的锁对象是一样的)
加在方法上作用范围是该方法体里面所有的代码,这是锁对象就是该类的实例
静态方法上锁对象用的是该类的class对象,而不是实例对象
所以当一个类的两个实例同时调用该类同一个非静态被synchronized修饰的方法的话不会造成同步阻塞,但是调用该类被synchronized修饰的静态方法的时候会造成阻塞同步(即便不是同一个静态方法,不同的静态方法,只要被synchronized修饰了,就都会阻塞同步,因为他们的锁对象是一样的,都是当前类的class对象)
3.synchronized的特性原子性:就是指一个操作或者多个操作要么全部不执行,要么全部执行,并且执行过程中不会被任何因素打断,被synchronized修饰的类或对象的所有操作都是原子的,因为在执行操作之前必须先获得类或对象的锁,直到执行完才能释放,这中间的过程无法被中断(除了已经废弃的stop()方法),即保证了原子性。
可见性:指的是多个线程访问一个资源时,该资源的状态,值信息等对其他线程都是可见的
synchronized和volatile都具有可见性,其中synchronized对一个类或对象加锁时,一个线程如果要访问该类或对象必须先获得它的锁,而这个锁的状态对于其他任何线程都是可见的,并且在释放锁之前会将对变量的修改刷新到主存当中,保证资源变量的可见性,如果某个线程占用了该锁,其他线程就必须在锁池中等待锁的释放。
而volatile的实现类似,被volatile修饰的变量,每当值需要修改时都会立即更新主存,主存是共享的,所有线程可见,所以确保了其他线程读取到的变量永远是最新值,保证可见性。
有序性:synchronized保证了每个时刻都只有一个线程访问同步代码块,也就确定了线程执行同步代码块是分先后顺序的,保证了有序性。
可重入性:当一个线程试图操作一个由其他线程持有的对象锁的临界资源时,将会处于阻塞状态,但当一个线程再次请求自己持有对象锁的临界资源时,这种情况属于重入锁。通俗一点讲就是说一个线程拥有了锁仍然还可以重复申请锁。
4.synchronized底层实现与优化了解底层实现之前,先要了解一下java的对象结构,java的对象结构主要分为三个部分:对象头,对象体,对齐字节,其中对象头使我们要关注的重点
对象头是实现锁的基础,因为synchronized申请锁,上锁,释放锁都与其有关系,,对象头主要有markword和class metadata address组成,其中mark word存储对象的hash code,锁信息或分代年龄,或GC标志等,class metadata address是类型指针指向对象的类元数据,JVM通过该指针确定该对象是哪个类的实例
锁也分不同的状态,jdk6之前只有两个状态:无锁和有锁(重量级锁),而在jdk6之后对synchronized进行了优化,新增了两种状态:偏向锁,轻量级锁,锁类型和状态都在对象头mark word里面都有记录,在申请锁,锁升级过程中JVM都需要读取对象的Mark word数据
每个锁都有一个



