修饰代码块
public class LockDemo1 {
private Object object = new Object();
public void testMonitor() {
synchronized (object) {
System.out.println("Monitor");
}
}
}
javap -c LockDemo1 反编译该类
monitorenter代表获取锁
monitorexit代表释放锁
synchronized修饰代码块是使用 monitorenter 和 monitorexit 来实现锁的获取和释放。默认情况下monitorexit 会有2个:一个正常退出,一个异常退出。
当发生异常时,只会触发第二个monitorexit
修饰实例方法
public class MySynchronized extends Thread{
public static void main(String[] args) {
MyClass myClass=new MyClass();
MyThread1 myThread1=new MyThread1(myClass);
MyThread2 myThread2=new MyThread2(myClass);
myThread1.start();
myThread2.start();
}
}
class MyClass{
public synchronized void hello(){
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Hello");
}
public synchronized void world(){
System.out.println("world");
}
}
class MyThread1 extends Thread{
private MyClass myClass;
public MyThread1(MyClass myClass) {
this.myClass = myClass;
}
@Override
public void run() {
myClass.hello();
}
}
class MyThread2 extends Thread{
private MyClass myClass;
public MyThread2(MyClass myClass) {
this.myClass = myClass;
}
@Override
public void run() {
myClass.world();
}
}
打印
Hello
world
改进方法
public class MySynchronized extends Thread{
public static void main(String[] args) {
MyClass myClass1=new MyClass();
MyClass myClass2=new MyClass();
MyThread1 myThread1=new MyThread1(myClass1);
MyThread2 myThread2=new MyThread2(myClass2);
myThread1.start();
myThread2.start();
}
}
-------------------------其余代码不变
打印
world
Hello
1.synchronized 修饰的实例方法相当于是对象锁,锁的是对象
2.当synchronized 修饰普通方法的时候,如果有多线程来访问同一对象的方法,那么同一时刻只能拥有一个线程获取到该对象的锁,也就是意味着:同一时刻只有一个线程在在执行,其他的线程处于等待状态.
修饰普通方法是通过字节码中的flags来标记的,如果flags中包含了ACC_SYNCHRONIZED,
那么JVM在执行时就知道这是一个同步方法,在调用时就会首先获取到该对象的Monitor对象.
其他线程则不能再获取Monitor对象,并陷入等待状态.直到该方法执行完并释放Monitor锁以后
其他线程才可以获取到该锁
修饰静态方法
public class MySynchronized extends Thread{
public static void main(String[] args) {
MyClass myClass1=new MyClass();
MyClass myClass2=new MyClass();
MyThread1 myThread1=new MyThread1(myClass1);
MyThread2 myThread2=new MyThread2(myClass2);
myThread1.start();
myThread2.start();
}
}
class MyClass{
public synchronized static void hello(){
try {
TimeUnit.MILLISECONDS.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Hello");
}
public synchronized static void world(){
System.out.println("world");
}
}
class MyThread1 extends Thread{
private MyClass myClass;
public MyThread1(MyClass myClass) {
this.myClass = myClass;
}
@Override
public void run() {
myClass.hello();
}
}
class MyThread2 extends Thread{
private MyClass myClass;
public MyThread2(MyClass myClass) {
this.myClass = myClass;
}
@Override
public void run() {
myClass.world();
}
}
打印
Hello
world
如果synchronized修饰的是静态方法,那么锁定的是类,该Class对象被所有的对象共享
修饰j静态方法是通过字节码中的flags来标记的,如果flags中包含了ACC_STATIC,ACC_SYNCHRONIZED,
那么JVM在执行时就知道这是一个J静态的同步方法,在调用时就会首先获取到Class对象的Monitor对象.
其他线程则不能再获取Monitor对象,并陷入等待状态.直到该方法执行完并释放Monitor锁以后
其他线程才可以获取到该锁