ReentrantLock基本使用

今天学习了java的lock和sychronized的区别,所以实践一下。

lock()方法实现懒汉式单例

package domain;

import java.util.concurrent.locks.ReentrantLock;

public class Singleton {
    private static volatile Singleton instance;

    private static ReentrantLock reentrantLock = new ReentrantLock();

    private Singleton() {
    }

    public static Singleton getInstance() {
        //double check
        if (instance == null) {
            try {
                reentrantLock.lock();
                if (instance == null) {
                    instance = new Singleton();
                }
            } finally {
                reentrantLock.unlock();
            }
        }
        return instance;
    }
}

condition实现进程通信

交替打印数字

package examples;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private static ReentrantLock reentrantLock = new ReentrantLock();
    private static Condition condition1 = reentrantLock.newCondition();
    private static Condition condition2 = reentrantLock.newCondition();

    public static void main(String[] args) {
        new Thread(() -> {
            try {
                reentrantLock.lock();
                for (int i = 1; i < 10; ++i) {
                    System.out.println(i);
                    condition2.signal();
                    condition1.await();
                }
                condition2.signal();//退出最后一个等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                reentrantLock.unlock();
            }

        }).start();

        new Thread(() -> {
            try {
                reentrantLock.lock();
                for (int i = 21; i < 30; ++i) {
                    System.out.println(i);
                    condition1.signal();
                    condition2.await();
                }
                condition1.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                reentrantLock.unlock();
            }
        }).start();
    }
}

输出结果:

1
21
2
22
3
23
4
24
5
25
6
26
7
27
8
28
9
29

使用lockInterruptibly()方法

lockInterruptibly()允许在等待时由其它线程调用等待线程的Thread.interrupt()方法来中断等待线程的等待而直接返回,这时不用获取锁,而会抛出一个InterruptedExceptionlock()方法不允许Thread.interrupt中断,即使检测到Thread.isInterrupted,一样会继续尝试获取锁,失败则继续休眠。只是在最后获取锁成功后再把当前线程置为interrupted状态,然后再中断线程。

package examples;

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private static ReentrantLock reentrantLock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            try {
                reentrantLock.lockInterruptibly();
                for (int i = 0; i < 10; ++i) {
                    Thread.sleep(3000);
                    System.out.println("线程" + Thread.currentThread().getName() + ": " + i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                reentrantLock.unlock();
            }
        }, "1");
        t1.start();
        //等5秒
        Thread.sleep(5000);

        Thread t2 = new Thread(() -> {
            try {
                reentrantLock.lock();
                System.out.println("线程" + Thread.currentThread().getName() + "获取到锁");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
            }
        }, "2");
        t2.start();
        //再等5秒
        Thread.sleep(5000);
        //等不及了
        System.out.println("中断t1");
        t1.interrupt();
    }
}

输出结果:

线程1: 0
线程1: 1
线程1: 2
中断t1
线程2获取到锁
java.lang.InterruptedException: sleep interrupted
at java.base/java.lang.Thread.sleep(Native Method)
at examples.ReentrantLockExample.lambda$main$0(ReentrantLockExample.java:13)
at java.base/java.lang.Thread.run(Thread.java:830)

tryLock()应用

忽略重复触发

tryLock()功能:如果已经获得锁立即返回false,起到防止重复而忽略的效果

package examples;

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private static ReentrantLock reentrantLock = new ReentrantLock();

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                if (reentrantLock.tryLock()) {
                    try {
                        System.out.println("线程" + Thread.currentThread().getName() + "获得锁");
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        reentrantLock.unlock();
                    }
                }
            }
        };

        for (int i = 0; i < 10; ++i) {
            new Thread(runnable, "" + i).start();
        }
    }
}

输出结果:

线程0获得锁

带参数tryLock:超时放弃

package examples;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private static ReentrantLock reentrantLock = new ReentrantLock();

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                try {
                    if (reentrantLock.tryLock(5, TimeUnit.SECONDS)) {
                        try {
                            System.out.println("线程" + Thread.currentThread().getName() + "获取到锁");
                            Thread.sleep(10000);
                        } finally {
                            reentrantLock.unlock();
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        new Thread(runnable, "1").start();
        new Thread(runnable, "2").start();//这个线程会超时,获取不到锁
    }
}

输出结果:

线程1获取到锁

参考

Java中ReentrantLock的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值