可重入锁

x33g5p2x  于2021-12-18 转载在 其他  
字(1.9k)|赞(0)|评价(0)|浏览(292)

1. 案例初体验

  1. public class T01_ReentrantLock1 {
  2. synchronized void m1() {
  3. for (int i = 0; i < 10; i++) {
  4. try {
  5. TimeUnit.SECONDS.sleep(1);
  6. } catch (InterruptedException e) {
  7. e.printStackTrace();
  8. }
  9. System.out.println(i);
  10. // 注释一
  11. // if (i == 2) {
  12. // m2();
  13. // }
  14. }
  15. }
  16. synchronized void m2() {
  17. System.out.println("m2...");
  18. }
  19. public static void main(String[] args) {
  20. T01_ReentrantLock1 rl = new T01_ReentrantLock1();
  21. new Thread(rl::m1).start();
  22. try {
  23. TimeUnit.SECONDS.sleep(1);
  24. } catch (InterruptedException e) {
  25. e.printStackTrace();
  26. }
  27. // 注释二
  28. // new Thread(rl::m2).start();
  29. }
  30. }

上方代码把注释二下方代码去掉注释,控制台输出如下:

  1. 0
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. 8
  10. 9
  11. m2...

可重入锁的意思是:在一个线程得到一个对象锁后,再次请求此对象锁是可以得到该对象锁的,这也说明在一个 sychronized 方法 / 代码块内部调用本类的其他 sychronized 方法 / 代码块时,是永远可以得到锁的。正是因为如此所以上面的控制台输出才是上面的样子,但如果只把注释一下方的代码去掉注释的话,控制台输出如下:

  1. 0
  2. 1
  3. 2
  4. m2...
  5. 3
  6. 4
  7. 5
  8. 6
  9. 7
  10. 8
  11. 9

锁重入支持继承的环境,当存在父子类继承关系时,子类可以通过锁重入调用父类的同步方法,示例代码如下:

  1. public class Run {
  2. public static void main(String[] args) {
  3. MyThread myThread = new MyThread();
  4. myThread.start();
  5. }
  6. }
  7. class MyThread extends Thread {
  8. @Override
  9. public void run() {
  10. Son son = new Son();
  11. son.sonMethod();
  12. }
  13. }
  14. class Son extends Person {
  15. public synchronized void sonMethod() {
  16. while (i > 0) {
  17. i--;
  18. System.out.println("Son " + i);
  19. super.personMethod();
  20. }
  21. }
  22. }
  23. class Person {
  24. public int i = 10;
  25. public synchronized void personMethod() {
  26. i--;
  27. System.out.println("Person " + i);
  28. }
  29. }

控制台输出如下:

  1. Son 9
  2. Person 8
  3. Son 7
  4. Person 6
  5. Son 5
  6. Person 4
  7. Son 3
  8. Person 2
  9. Son 1
  10. Person 0

2. ReentrantLock

ReentrantLock 需要手动释放锁。

代码意思和上面的一样。

  1. public class T02_ReentrantLock2 {
  2. Lock reentrantLock = new ReentrantLock();
  3. void m1() {
  4. try {
  5. reentrantLock.lock();
  6. for (int i = 0; i < 10; i++) {
  7. TimeUnit.SECONDS.sleep(1);
  8. System.out.println(i);
  9. // 注释一
  10. // if (i == 2) {
  11. // m2();
  12. // }
  13. }
  14. } catch (InterruptedException e) {
  15. e.printStackTrace();
  16. } finally {
  17. reentrantLock.unlock();
  18. }
  19. }
  20. void m2() {
  21. try {
  22. reentrantLock.lock();
  23. System.out.println("m2...");
  24. } finally {
  25. reentrantLock.unlock();
  26. }
  27. }
  28. public static void main(String[] args) {
  29. T02_ReentrantLock2 rl = new T02_ReentrantLock2();
  30. new Thread(rl::m1).start();
  31. try {
  32. TimeUnit.SECONDS.sleep(1);
  33. } catch (InterruptedException e) {
  34. e.printStackTrace();
  35. }
  36. // 注释二
  37. // new Thread(rl::m2).start();
  38. }
  39. }

相关文章