1.synchronized关键字的作用和用法
使用synchronized修饰的方法或则代码块,具有同步的特性,即同一时间最多只有一个线程能执行这段代码,实现了多线程的同步执行。
用法
a) 用于普通方法
示例:
public synchronized void sayHello(String str){
System.out.println(“hello~”+str);
}
这种用法是对当前对象加锁,最多一个线程能执行当前对象的synchoronized方法。
b) 用于静态方法
public static synchronized void sayHello(String str){
System.out.println(“hello~”+str);
}
对类方法所属的类的class对象加锁,最多一个线程能执行当前类的synchronized静态方法。
c) 用于代码块
public void sayHello(String str){
synchronized(object|class){
System.out.println(“hello~”+str);
}
}
可对普通实例对象加锁也可以对class对象加锁。
2.synchronized原理
每一个对象都有一个monitor内置对象,线程要执行被synchronized修饰的方法或代码块,必须要获得monitor的所有权。
一个同步方法会被编译器编译成如下的样子:
源码:
public class SynchronizedDemo { public void method() { synchronized (this) { System.out.println("Method 1 start"); } } } |
反编译.class字节码文件
如图,一个同步方法代码在执行前会先执行请求对对象的monitor加锁的指令,在代码执行结束后再释放对monitor的锁以便其他线程对monitor加锁。
具体流程是这样:
1).一个线程在执行一个同步方法时,如果该线程还没有对monitor加锁,会先去看对象的monitor进入数是否为0——如果为0:请求对monitor加锁,然后monitor的进入数会加一;如果不为0:线程会进入阻塞状态知道monitor的进入数变成0(以及获得资源比如时间片)再去对monitor请求加锁。
若果该线程已经对monitor加锁,monitor的进入数会加一。
2).当代码执行结束后, monitor的进入数会减一,如果monitor恰好变为0,会释放monitor。