一、使用
public class SynchronizedDemo {
private static int num=0;
// 同步方法:对象锁
public synchronized void test1(){
num++;
}
// 同步方法:类锁
public static synchronized void test2(){
num++;
}
// 同步代码块:对象锁
Object obj=new Object();
public void test3(){
synchronized(obj){
// dosomething
num++;
}
}
// 同步代码块:类锁
public void test4(){
synchronized(SynchronizedDemo.class){
// dosomething
num++;
}
}
}
二、原理
1. 同步方法
编译后产生的字节码文件中,该方法的访问标识增加了一个
ACC_SYNCHRONIZED
,线程执行时会识别该标记,获取对应的锁,实现方法同步。

2. 同步代码块
编译产生的字节码中,在同步代码块前插入
monitorenter
指令,在同步代码块结束处和异常处插入monitorexit
指令

任意一个对象都拥有自己的监视器(monitor),对象有锁计数器,monitorenter成功一次,计数器加1;monitorexit,计数器减1。锁计数器为0时,表示其他线程可获取该对象的监视器。上述两种方法的本质都是对一个对象的监视器的获取。同步方法或同步代码块时,执行方法的线程获取了对象的监视器才能进入同步方法或同步代码块,获取不到的话进入同步队列,当成功获取监视器的线程释放监视器后,同步队列中的线程才会被唤醒,重新尝试获取监视器。

三、与Lock的比较(为什么有了synchronized还要有Lock)

网友评论