在Java中,每一个线程都有一个内部锁。当我们使用synchronized关键字时,就是利用这个内部锁来实现线程对某个对象的锁定控制。
那么,如果某个对象中有两个方法,方法一和方法二都使用了synchronized关键字。如果线程一执行该对象的方法一,线程二执行该对象的方法二。如果线程1一直不释放该对象的内部锁的话,那么线程二应该无法执行该对象的方法二。下面就用代码来验证一下。
首先,定义一个Task类。
1 package corejava.chapter14; 2 3 public class TaskC { 4 5 public synchronized void method1() throws InterruptedException { 6 7 while (true) { 8 System.out.println("我是方法1"); 9 Thread.sleep(10000); 10 } 11 12 } 13 14 public synchronized void method2() throws InterruptedException { 15 16 while (true) { 17 System.out.println("我是方法2"); 18 Thread.sleep(10000); 19 } 20 21 } 22 23 }
method1每隔10秒就会输出一句“我是方法1”。method2每隔10秒就会输出一句“我是方法2”。两个方法都使用了synchronized关键字。
再定义两个执行类ExecutorC1和Executor2。
1 package corejava.chapter14; 2 3 public class ExecutorC1 implements Runnable { 4 5 private TaskC taskC; 6 7 public ExecutorC1(TaskC taskC) { 8 this.taskC = taskC; 9 } 10 11 @Override 12 public void run() { 13 try { 14 taskC.method1(); 15 } catch (Exception e) { 16 e.printStackTrace(); 17 } 18 19 } 20 }
1 package corejava.chapter14; 2 3 public class ExecutorC2 implements Runnable { 4 5 private TaskC taskC; 6 7 public ExecutorC2(TaskC taskC) { 8 this.taskC = taskC; 9 } 10 11 @Override 12 public void run() { 13 try { 14 taskC.method2(); 15 } catch (Exception e) { 16 e.printStackTrace(); 17 } 18 19 } 20 21 }
执行类1启动线程后,会执行taskC的method1方法。执行类启动线程后,会执行taskC的method2方法。
最后定义入口类Main
1 package corejava.chapter14; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 TaskC taskC = new TaskC(); 7 ExecutorC1 executorC1 = new ExecutorC1(taskC); 8 ExecutorC2 executorC2 = new ExecutorC2(taskC); 9 Thread thread1 = new Thread(executorC1); 10 Thread thread2 = new Thread(executorC2); 11 thread1.start(); 12 thread2.start(); 13 } 14 15 }
执行对象1和执行对象2都使用同一个taskC去实例化,这样他们之间就会存在竞争。当thread1执行taskC的method1时,会一直持有taskC的内部锁,因此thread2将一直处于阻塞状态。
下面是运行输出结果

可见,确实如我们所料,虽然两个线程要执行的是不同的方法,但因为线程1一直“霸占”着内部锁,所以线程2始终在阻塞状态,得不到执行。
所以,如果我们在对某个类要使用synchronized关键字进行锁定控制时,一定要牢记它使用的是该类的内部锁。它是唯一的。当多个方法都用它来进行控制时,一定要考虑这一点。
浙公网安备 33010602011771号