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关键字进行锁定控制时,一定要牢记它使用的是该类的内部锁。它是唯一的。当多个方法都用它来进行控制时,一定要考虑这一点。