Java synchronized 两把锁的执行顺序
1. 整件事情的流程
在理解Java synchronized 两把锁为何会按顺序执行前,首先需要了解以下几个概念:
- Synchronized关键字:用于修饰方法或代码块,保证同一时刻只有一个线程可以访问被修饰的方法或代码块。
- 对象锁:Java中的每个对象都有一个内置的锁,也称为监视器锁。当一个线程访问一个方法或代码块时,会先获取该对象的锁,其他线程在获取锁之前会被阻塞。
- 临界区:指的是一段代码,同一时刻只允许一个线程进入执行。
考虑以下代码片段:
public class MyClass {
private Object lock1 = new Object();
private Object lock2 = new Object();
public void method1() {
synchronized (lock1) {
// 第一段同步代码块
}
}
public void method2() {
synchronized (lock2) {
// 第二段同步代码块
}
}
}
在以上示例中,有两个方法method1
和method2
,分别对应两段不同的同步代码块。这两段代码块使用了不同的对象锁lock1
和lock2
。
当一个线程执行method1
方法时,它会获取lock1
对象的锁,进入第一段同步代码块执行。同样地,当一个线程执行method2
方法时,它会获取lock2
对象的锁,进入第二段同步代码块执行。
2. 每一步需要做什么
下面我们逐步解释每一步需要做什么,以及对应的代码。
第一步:创建自定义类MyClass
public class MyClass {
private Object lock1 = new Object();
private Object lock2 = new Object();
// ...
}
在这一步中,我们创建了一个自定义类MyClass
,并定义了两个对象锁lock1
和lock2
。
第二步:定义method1
方法
public void method1() {
synchronized (lock1) {
// 第一段同步代码块
}
}
在这一步中,我们定义了method1
方法,使用synchronized
关键字修饰,参数为lock1
。这意味着在调用method1
方法时,只有获得lock1
对象锁的线程才能进入第一段同步代码块执行。
第三步:定义method2
方法
public void method2() {
synchronized (lock2) {
// 第二段同步代码块
}
}
在这一步中,我们定义了method2
方法,使用synchronized
关键字修饰,参数为lock2
。这意味着在调用method2
方法时,只有获得lock2
对象锁的线程才能进入第二段同步代码块执行。
第四步:创建多个线程并调用方法
public static void main(String[] args) {
MyClass myObject = new MyClass();
Thread thread1 = new Thread(new Runnable() {
public void run() {
myObject.method1();
}
});
Thread thread2 = new Thread(new Runnable() {
public void run() {
myObject.method2();
}
});
thread1.start();
thread2.start();
}
在这一步中,我们创建了一个MyClass
对象myObject
。然后创建了两个线程thread1
和thread2
,分别调用myObject
的method1
和method2
方法。
3. 代码注释
下面是以上代码中需要使用的每一条代码,并附带注释说明:
public class MyClass {
private Object lock1 = new Object(); // 创建对象锁lock1
private Object lock2 = new Object(); // 创建对象锁lock2
public void method1() {
synchronized (lock1) { // 使用lock1对象锁
// 第一段同步代码块
}
}
public void method2() {
synchronized (lock2