目的 为了证明线程获取到对象锁之后该对象不会被释放掉直到当前线程执行完,其他线程才可以获取这些对象的锁
1、重入锁
一个线程调用synchronized修饰的方法时会获取到该对象锁,当前线程再次获取到该对象锁,表现锁的重入性。
2、例子
2.1、设计思路
设计思路:
* 有A B C 三个类对象
* 线程thread : a调用b类方法, b类调用c类方法,c类调用a方法
* 线程thread2: 直接调用a方法
* 线程thread3:直接调用b方法
* 线程thread4:直接调用c方法 ( 在调用thread4调用c类方法时候休眠5s,这个目的是为了让线程thread获取c对象的锁)
2.2 A.java
public class A {
public synchronized void printA(B b, C c) {
System.out.println("A-A method,线程名:" + Thread.currentThread().getName());
b.printA(this, c);
}
public synchronized void printB() {
System.out.println("A-B method,线程名:" + Thread.currentThread().getName());
printC();
}
/**
* 这个地方为了证明调用A对象的方法,只要获取b对象的锁必须要等该整个线程执行完,刚刚b对象是否被释放了,实验证明b对象并没有被释放
* 也就是说线程thread必须要全部执行完,才会释放所有对象(A,B ,C对象)的锁,虽然它们此时并不需要对象就行方法调用
*/
public synchronized void printC() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("A-C method,线程名:" + Thread.currentThread().getName());
}
/**
* 设计思路:
* 有A B C 三个类对象
* 线程thread : a调用b类方法, b类调用c类方法,c类调用a方法
* 线程thread2: 直接调用a方法
* 线程thread3:直接调用b方法
* 线程thread4:直接调用c方法 ( 在调用thread4调用c类方法时候休眠5s,这个目的是为了让线程thread获取c对象的锁)
* thread 此时获取到a b c三个对象的锁,只有拿到手就不会释放,直到thread线程执行完毕之后才会释放 a b c的锁,这也是
* 锁的重入性,只要获取对象,就可以再次获取到锁(原因是,该对象一直被当前线程拿在手里,当然可以再次到该对象的锁)
*
*
* @param args
*/
public static void main(String[] args) {
A a = new A();
B b = new B();
C c = new C();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
a.printA(b,c);
}
});
thread.start();
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
a.printB();
System.out.println("线程thread2");
}
});
thread2.start();
Thread thread3 = new Thread(new Runnable() {
@Override
public void run() {
b.printB();
System.out.println("线程thread3");
}
});
thread3.start();
Thread thread4 = new Thread(new Runnable() {
@Override
public void run() {
try {
//为让thread4晚于thread线程获取锁,为了证明线程一旦获取到对象的锁的时候必须要等整个方法执行完才会释放所有对象的锁,这个也是说明锁的重入问题
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
c.printB();
System.out.println("线程thread4");
}
});
thread4.start();
/***********print***********************/
/**
* A-A method,线程名:Thread-0
* B-A method,线程名:Thread-0
* C-A method,线程名:Thread-0
* 此时有线程获取c对象锁
* A-B method,线程名:Thread-0
* A-C method,线程名:Thread-0
* C-B method,线程名:Thread-3
* B-B method,线程名:Thread-2
* A-B method,线程名:Thread-1
* 线程thread3
* 线程thread4
* A-C method,线程名:Thread-1
* 线程thread2
*/
}
}
2.3 B.java
public class B {
public synchronized void printA(A a, C c) {
System.out.println("B-A method,线程名:" + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
c.printA(a);
}
public synchronized void printB() {
System.out.println("B-B method,线程名:" + Thread.currentThread().getName());
}
}
2.4 C.java
public class C {
public synchronized void printA(A a) {
System.out.println("C-A method,线程名:" + Thread.currentThread().getName());
System.out.println("此时有线程获取c对象锁");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
a.printB();
}
public synchronized void printB() {
System.out.println("C-B method,线程名:" + Thread.currentThread().getName());
}
}
2.5、打印结果
总结
- 线程只要获取某个对象的锁,那么它就不会被释放,直到线程结束才会被释放
- 抛出运行时异常会对象释放锁(这个在该例子中没有被体现)
- 详细可以看例子注释
有不同看法欢迎交流,谢谢大佬们