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