synchronized锁的是对象而不是代码,可加在方法上或者代码块。如果将synchronized加在静态方法上,则锁的是该类的Class对象;加在普通方法上锁的是this当前对象;也可在类中定义私有变量Object o如:synchronized(o){...},锁定自定义对象。不过需要注意类中定义的被锁对象不能是String常量,Integer,Long等类型。
一个类中被synchronized锁定的方法和另外的非锁定方法可同时执行。另外synchronized有个锁升级的过程:在jdk1.6之前,synchronized为重量级锁,需要触及OS以及用户态到内核态的来回切换。不过jdk1.6之后,采用偏向锁(被锁对象Object的markword里会记录首个锁住该对象的线程id,偏向于该线程再次获得锁)->自旋锁(如果线程争用,从偏向锁升级为自旋锁,一个线程执行,另外线程自旋等待;自旋10次以后升级为重量级锁)->重量级锁,之间通过锁碰撞进行切换。
若程序执行时间短(加锁代码),线程数较少,则用自旋;程序执行时间长,线程数多,用系统锁。
volatile:保持可见性(即一个线程在自己的内存空间中修改自己从堆内存上读取的变量值时,其修改后其他使用该值的线程能够立刻看到该值发生的变化),但不能保证原子性,底层涉及MESI以及缓存一致性协议;禁止指令重排序(使用内存屏障禁止汇编级指令乱序执行),详见DCL单例、JMM(java内存模型)以及loadfence、storefence等原语指令。