Contents

在Java中,每一个线程都有一个内部锁。当我们使用synchronized关键字时,就是利用这个内部锁来实现线程对某个对象的锁定控制。
那么,如果某个对象中有两个方法,方法一和方法二都使用了synchronized关键字。如果线程一执行该对象的方法一,线程二执行该对象的方法二。如果线程1一直不释放该对象的内部锁的话,那么线程二应该无法执行该对象的方法二。下面就用代码来验证一下。
首先,定义一个Task类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package corejava.chapter14;
public class TaskC {
public synchronized void method1() throws InterruptedException {
while (true) {
System.out.println("我是方法1");
Thread.sleep(10000);
}
}
public synchronized void method2() throws InterruptedException {
while (true) {
System.out.println("我是方法2");
Thread.sleep(10000);
}
}
}

method1每隔10秒就会输出一句“我是方法1”。method2每隔10秒就会输出一句“我是方法2”。两个方法都使用了synchronized关键字。

再定义两个执行类ExecutorC1和Executor2。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package corejava.chapter14;
public class ExecutorC1 implements Runnable {
private TaskC taskC;
public ExecutorC1(TaskC taskC) {
this.taskC = taskC;
}
@Override
public void run() {
try {
taskC.method1();
} catch (Exception e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package corejava.chapter14;
public class ExecutorC2 implements Runnable {
private TaskC taskC;
public ExecutorC2(TaskC taskC) {
this.taskC = taskC;
}
@Override
public void run() {
try {
taskC.method2();
} catch (Exception e) {
e.printStackTrace();
}
}
}

执行对象1和执行对象2都使用同一个taskC去实例化,这样他们之间就会存在竞争。当thread1执行taskC的method1时,会一直持有taskC的内部锁,因此thread2将一直处于阻塞状态。

下面是运行输出结果

可见,确实如我们所料,虽然两个线程要执行的是不同的方法,但因为线程1一直“霸占”着内部锁,所以线程2始终在阻塞状态,得不到执行。

所以,如果我们在对某个类要使用synchronized关键字进行锁定控制时,一定要牢记它使用的是该类的内部锁。它是唯一的。当多个方法都用它来进行控制时,一定要考虑这一点。

Contents