可重入锁和不可重入锁的区别

你的名字 2022-12-17 07:29 281阅读 0赞

不可重入锁示例(同一个线程不可以重入上锁后的代码段)

如下是一个不可重入锁的逻辑过程,会发现执行main方法控制台会打印执行doJob方法前,然后就会一直线程阻塞,不会打印执行doJob方法过程中,原因在于第一次上锁后,由于没有释放锁,因此执行第一次lock后isLocked = true,这个时候调用doJob()内部又一次调用了lock()由于上个线程将isLocked = true,导致再次进入的时候就进入死循环。导致线程无法执行System.out.println("执行doJob方法过程中");这行代码,因此控制台只能打印执行doJob方法前。这种现象就造成了不可重入锁

  1. public class Count{
  2. MyLock lock = new MyLock();
  3. public static void main(String[] args) throws InterruptedException {
  4. new Count().doSomeThing(); // 示例的main方法
  5. }
  6. public void doSomeThing() throws InterruptedException {
  7. lock.lock(); // 第一次上锁
  8. System.out.println("执行doJob方法前");
  9. doJob(); // 方法内会再次上锁
  10. lock.unlock(); // 释放第一次上的锁
  11. }
  12. public void doJob() throws InterruptedException {
  13. lock.lock();
  14. System.out.println("执行doJob方法过程中");
  15. lock.unlock();
  16. }
  17. }
  18. /** * 自定义锁 */
  19. class MyLock{
  20. private boolean isLocked = false;
  21. public synchronized void lock() throws InterruptedException{
  22. while(isLocked){
  23. wait();
  24. }
  25. isLocked = true; // 线程第一次进入后就会将器设置为true,第二次进入是就会由于where true进入死循环
  26. }
  27. public synchronized void unlock(){
  28. isLocked = false; // 将这个值设置为false目的是释放锁
  29. notify(); // 接触阻塞
  30. }
  31. }

可重入锁示例(同一个线程可以重入上锁的代码段,不同的线程则需要进行阻塞)

java的可重入锁有:ReentrantLock(显式的可重入锁)synchronized(隐式的可重入锁)

可重入锁诞生的目的就是防止上面不可重入锁的那种情况,导致同一个线程不可重入上锁代码段。

目的就是让同一个线程可以重新进入上锁代码段。

设计可重入锁的示例代码

  1. public class MyReentrantLock {
  2. boolean isLocked = false; // 默认没有上锁
  3. Thread lockedBy = null; // 记录阻塞线程
  4. int lockedCount = 0; // 上锁次数计数
  5. /** * 上锁逻辑 */
  6. public synchronized void lock() throws InterruptedException {
  7. Thread thread = Thread.currentThread();
  8. // 上锁了 并且 如果是同一个线程则放行,否则其它线程需要进入where循环进行等待
  9. while (isLocked && lockedBy != thread) {
  10. wait();
  11. }
  12. isLocked = true; // 第一次进入就进行上锁
  13. lockedCount++; // 上锁次数计数
  14. lockedBy = thread; // 当前阻塞的线程
  15. }
  16. /** * 释放锁逻辑 */
  17. public synchronized void unlock() {
  18. if (Thread.currentThread() == this.lockedBy) {
  19. lockedCount--; // 将上锁次数减一
  20. if (lockedCount == 0) { // 当计数为0,说明所有线程都释放了锁
  21. isLocked = false; // 真正的将释放了所有锁
  22. notify();
  23. }
  24. }
  25. }
  26. }

发表评论

表情:
评论列表 (有 0 条评论,281人围观)

还没有评论,来说两句吧...

相关阅读