可重入锁

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

1. 案例初体验

public class T01_ReentrantLock1 {
    synchronized void m1() {
        for (int i = 0; i < 10; i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i);
// 注释一
// if (i == 2) {
// m2();
// }
        }
    }

    synchronized void m2() {
        System.out.println("m2...");
    }

    public static void main(String[] args) {
        T01_ReentrantLock1 rl = new T01_ReentrantLock1();
        new Thread(rl::m1).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
// 注释二
// new Thread(rl::m2).start();
    }
}

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

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

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

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

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

public class Run {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        Son son = new Son();
        son.sonMethod();
    }
}

class Son extends Person {
    public synchronized void sonMethod() {
        while (i > 0) {
            i--;
            System.out.println("Son " + i);
            super.personMethod();
        }
    }
}

class Person {
    public int i = 10;
    
    public synchronized void personMethod() {
        i--;
        System.out.println("Person " + i);
    }
}

控制台输出如下:

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

2. ReentrantLock

ReentrantLock 需要手动释放锁。

代码意思和上面的一样。

public class T02_ReentrantLock2 {
    Lock reentrantLock = new ReentrantLock();

    void m1() {
        try {
            reentrantLock.lock();
            for (int i = 0; i < 10; i++) {
                TimeUnit.SECONDS.sleep(1);
                System.out.println(i);
// 注释一
// if (i == 2) {
// m2();
// }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantLock.unlock();
        }

    }

    void m2() {
        try {
            reentrantLock.lock();
            System.out.println("m2...");
        } finally {
            reentrantLock.unlock();
        }
    }

    public static void main(String[] args) {
        T02_ReentrantLock2 rl = new T02_ReentrantLock2();
        new Thread(rl::m1).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
// 注释二
// new Thread(rl::m2).start();
    }
}

相关文章