Synchronized锁


可重入锁

  可重入锁指的是在一个线程中可以多次获取同一把锁,比如:一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接获取锁执行调用的方法,而无需重新获得锁。重入则避免了死锁情况的发生。

  例如:当线程1访问testA时,线程2不能访问testB方法,但是可以访问testC;同样,线程2访问testB时,线程1不能访问testA,但是仍然可以访问testC。

  此时,若线程1调用了testA方法,testA方法内调用了testC方法,其他线程同时访问testC方法,若testC方法修改了类成员变量(Java方法里面的局部变量是不存在并发问题的。每个线程都有自己独立的调用栈,局部变量保存在各自的调用栈中,不会被共享,自然也就没有并发问题),就会造成线程安全问题。

测试类:

 1 public class TestLock {
 2 
 3     synchronized void testA() throws Exception {
 4         System.out.println(Thread.currentThread().getName() + ":this is testA");
 5         Thread.sleep(2000);
 6         testB();
 7         System.out.println(Thread.currentThread().getName() + ":testA is over");
 8     }
 9 
10     synchronized void testB() throws Exception {
11         System.out.println(Thread.currentThread().getName() + ":this is testB");
12         Thread.sleep(2000);
13         System.out.println(Thread.currentThread().getName() + ":testB is over");
14     }
15 
16     public void testC() {
17         System.out.println(Thread.currentThread().getName() + ":this is testC");
18     }
19 
20 }

main 测试方法中创建两个线程访问上述方法:

 1 public class TestLockMain {
 2 
 3     public static void main(String[] args) {
 4         TestLock ts = new TestLock();
 5 
 6         new Thread(new Runnable() {
 7             @Override
 8             public void run() {
 9                 try {
10                     ts.testA();
11                 } catch (Exception e) {
12                     e.printStackTrace();
13                 }
14             }
15         }, "线程1").start();
16 
17         new Thread(new Runnable() {
18             @Override
19             public void run() {
20                 try {
21                     ts.testC();
22                 } catch (Exception e) {
23                     e.printStackTrace();
24                 }
25             }
26         }, "线程2").start();
27 
28     }
29 
30 }

执行结果:

线程1:this is testA
线程2:this is testC
线程1:this is testB
线程1:testB is over
线程1:testA is over