ReentrantLock重入锁

1使用案例

public class ReenterLock implements Runnable{
    public static ReentrantLock lock=new ReentrantLock();
    public static int i=0;
    @Override
    public void run() {
        for (int j = 0; j <100; j++) {
            lock.lock();
        try{
            i++;
            System.out.println(Thread.currentThread().getName()+" "+i);
        }finally {
            lock.unlock();
        }
        }
    }
    public static void main(String[] args)throws InterruptedException{
        ReenterLock r1=new ReenterLock();
        Thread t1=new Thread(r1);
        Thread t2=new Thread(r1);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
Thread-0 10
Thread-0 11
Thread-0 12
Thread-0 13
Thread-0 14
Thread-0 15
Thread-0 16
Thread-0 17
Thread-0 18
Thread-0 19
Thread-0 20
Thread-0 21
Thread-0 22
Thread-0 23
Thread-0 24
Thread-0 25
Thread-0 26
Thread-0 27
Thread-0 28
Thread-0 29
Thread-0 30
Thread-0 31
Thread-0 32
Thread-0 33
Thread-0 34
Thread-0 35
Thread-0 36
Thread-0 37
Thread-0 38
Thread-0 39
Thread-0 40
Thread-0 41
Thread-0 42
Thread-0 43
Thread-0 44
Thread-0 45
Thread-0 46
Thread-0 47
Thread-0 48
Thread-0 49
Thread-0 50
Thread-0 51
Thread-0 52
Thread-0 53
Thread-0 54
Thread-0 55
Thread-0 56
Thread-0 57
Thread-0 58
Thread-0 59
Thread-0 60
Thread-0 61
Thread-0 62
Thread-0 63
Thread-0 64
Thread-0 65
Thread-0 66
Thread-0 67
Thread-0 68
Thread-0 69
Thread-0 70
Thread-0 71
Thread-0 72
Thread-0 73
Thread-0 74
Thread-0 75
Thread-0 76
Thread-0 77
Thread-0 78
Thread-0 79
Thread-0 80
Thread-0 81
Thread-0 82
Thread-0 83
Thread-0 84
Thread-0 85
Thread-0 86
Thread-0 87
Thread-0 88
Thread-0 89
Thread-0 90
Thread-0 91
Thread-0 92
Thread-0 93
Thread-0 94
Thread-0 95
Thread-0 96
Thread-0 97
Thread-0 98
Thread-0 99
Thread-0 100
Thread-1 101
Thread-1 102
Thread-1 103
Thread-1 104
Thread-1 105
Thread-1 106
Thread-1 107
Thread-1 108
Thread-1 109
Thread-1 110
Thread-1 111
Thread-1 112
Thread-1 113
Thread-1 114
Thread-1 115
Thread-1 116
Thread-1 117
Thread-1 118
Thread-1 119
Thread-1 120
Thread-1 121
Thread-1 122
Thread-1 123
Thread-1 124
Thread-1 125
Thread-1 126
Thread-1 127
Thread-1 128
Thread-1 129
Thread-1 130
Thread-1 131
Thread-1 132
Thread-1 133
Thread-1 134
Thread-1 135
Thread-1 136
Thread-1 137
Thread-1 138
Thread-1 139
Thread-1 140
Thread-1 141
Thread-1 142
Thread-1 143
Thread-1 144
Thread-1 145
Thread-1 146
Thread-1 147
Thread-1 148
Thread-1 149
Thread-1 150
Thread-1 151
Thread-1 152
Thread-1 153
Thread-1 154
Thread-1 155
Thread-1 156
Thread-1 157
Thread-1 158
Thread-1 159
Thread-1 160
Thread-1 161
Thread-1 162
Thread-1 163
Thread-1 164
Thread-1 165
Thread-1 166
Thread-1 167
Thread-1 168
Thread-1 169
Thread-1 170
Thread-1 171
Thread-1 172
Thread-1 173
Thread-1 174
Thread-1 175
Thread-1 176
Thread-1 177
Thread-1 178
Thread-1 179
Thread-1 180
Thread-1 181
Thread-1 182
Thread-1 183
Thread-1 184
Thread-1 185
Thread-1 186
Thread-1 187
Thread-1 188
Thread-1 189
Thread-1 190
Thread-1 191
Thread-1 192
Thread-1 193
Thread-1 194
Thread-1 195
Thread-1 196
Thread-1 197
Thread-1 198
Thread-1 199
Thread-1 200
200

// lock.unlock();
屏蔽 lock.unlock()这行代码的打印结果,加锁后必须释放锁,否则其他线程无法获取资源

Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
Thread-0 10
Thread-0 11
Thread-0 12
Thread-0 13
Thread-0 14
Thread-0 15
Thread-0 16
Thread-0 17
Thread-0 18
Thread-0 19
Thread-0 20
Thread-0 21
Thread-0 22
Thread-0 23
Thread-0 24
Thread-0 25
Thread-0 26
Thread-0 27
Thread-0 28
Thread-0 29
Thread-0 30
Thread-0 31
Thread-0 32
Thread-0 33
Thread-0 34
Thread-0 35
Thread-0 36
Thread-0 37
Thread-0 38
Thread-0 39
Thread-0 40
Thread-0 41
Thread-0 42
Thread-0 43
Thread-0 44
Thread-0 45
Thread-0 46
Thread-0 47
Thread-0 48
Thread-0 49
Thread-0 50
Thread-0 51
Thread-0 52
Thread-0 53
Thread-0 54
Thread-0 55
Thread-0 56
Thread-0 57
Thread-0 58
Thread-0 59
Thread-0 60
Thread-0 61
Thread-0 62
Thread-0 63
Thread-0 64
Thread-0 65
Thread-0 66
Thread-0 67
Thread-0 68
Thread-0 69
Thread-0 70
Thread-0 71
Thread-0 72
Thread-0 73
Thread-0 74
Thread-0 75
Thread-0 76
Thread-0 77
Thread-0 78
Thread-0 79
Thread-0 80
Thread-0 81
Thread-0 82
Thread-0 83
Thread-0 84
Thread-0 85
Thread-0 86
Thread-0 87
Thread-0 88
Thread-0 89
Thread-0 90
Thread-0 91
Thread-0 92
Thread-0 93
Thread-0 94
Thread-0 95
Thread-0 96
Thread-0 97
Thread-0 98
Thread-0 99
Thread-0 100

有显示的操作过程,必须显示指定何时加锁,何时释放锁。加锁后必须释放锁。
2重入含义
ReentrantLock是可以反复进入的,反复仅仅限于一个线程。一个线程连续两次获得同一把锁是允许的,如果不允许这种操作,线程在第二次申请锁的时候会和自己发生死锁。一个线程加多少次锁,必须释放多少次锁,如果释放的次数少,相当于线程还持有这个锁,其他线程无法
获取资源。

            lock.lock();
            lock.lock();
        try{
            i++;
            System.out.println(Thread.currentThread().getName()+" "+i);
        }finally {
            lock.unlock();
            lock.unlock();

3可中断的锁
对于synchronized来说,一个线程在等待锁,结果要么是获得锁,要么就是保持等待的状态。使用重入锁,线程在等待的过程中,程序可以根据需要取消对锁的请求。这对于处理死锁有一定帮助。

public class IntLock implements Runnable{
    @Override
    public void run() {
        try{
            if(lock==1) {
            //获取锁操作
                lock1.lockInterruptibly();
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
                lock2.lockInterruptibly();
            }else{
                lock2.lockInterruptibly();
                try{
                    Thread.sleep(500);
                }catch(InterruptedException e){}
                lock1.lockInterruptibly();

            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally{
            if(lock1.isHeldByCurrentThread())
                lock1.unlock();
            if(lock2.isHeldByCurrentThread())
                lock2.unlock();
            System.out.println(Thread.currentThread().getId()+":线程退出");
        }

    }
    public static ReentrantLock lock1=new ReentrantLock();
    public static ReentrantLock lock2=new ReentrantLock();
    int lock;
    public IntLock(int lock){
        this.lock=lock;
    }
    public static void main(String[] args)throws InterruptedException{
        IntLock r1=new IntLock(1);
        IntLock r2=new IntLock(2);
        Thread t1=new Thread(r1);
        Thread t2=new Thread(r2);
        t1.start();
        t2.start();
        Thread.sleep(1000);
        t2.interrupt();
    }

}

执行结果:
10:线程退出
9:线程退出
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:898)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1222)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at IntLock.run(IntLock.java:22)
at java.lang.Thread.run(Thread.java:745)

Process finished with exit code 0
线程t1和t2启动后,t1先占用lock1,再占用lock2,t2先占用lock2,再占用lock1,lock.lockInterruptibly()是一个可以对中断进行响应的锁操作,即在锁的等待过程中可以响应中断。两个线程都在等待对方释放锁,两个线程处于死锁状态,执行 t2.interrupt()操作后,t2线程被中断,t2会放弃对lock1的申请,同时释放lock2,线程t1获得lock2锁,继续执行,最后两个线程都退出,t1真正完成工作,t2线程放弃任务直接退出释放资源。
4tryLock()/tryLock(long time,TimeUnit unpublic class TimeLock implements Runnable {
public static ReentrantLock lock=new ReentrantLock();

@Override
public void run() {
    try{
        if(lock.tryLock(5, TimeUnit.SECONDS)){
            Thread.sleep(6000);
        }else{
            System.out.println("get lock failed");
        }
    }catch (InterruptedException e){
        e.printStackTrace();
    }finally{
        if(lock.isHeldByCurrentThread())lock.unlock();
    }
}
public static void main(String[] args){
    TimeLock t1=new TimeLock();
    Thread th1=new Thread(t1);
    Thread th2=new Thread(t1);
    th1.start();
    th2.start();
}

}
如果超过5秒没有得到锁就会返回false,占用锁的线程持用锁的时间长达6秒,因此另外一个线程无法在5秒的等待时间内获得锁。
锁在大多数情况下,锁的申请都是非公平的,系统会随机地从锁的等待队列中挑选一个。公平的锁会按时间先后顺序,保证先到者先得后到者后得。公平锁的一大特点是:不会产生饥饿。在使用synchronized关键字进行锁控制时,产生的锁是非公平的。
公平锁的创建:
public ReentrantLock(boolean fair)
ReentrantLock lock=new ReentrantLock(true);
实现公平锁必然要维护一个有序队列,因此公平锁的实现成本比较高,性能相对也非常低,默认情况下,锁是非公平的。

public class FairLock implements Runnable {
    public static ReentrantLock fairLock = new ReentrantLock(true);

    @Override
    public void run() {
        while (true) {
            try {
                fairLock.lock();
                System.out.println(Thread.currentThread().getName() + "获得锁");
            } finally {
                fairLock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        FairLock r1 = new FairLock();
        Thread t1 = new Thread(r1, "Thread_t1");
        Thread t2 = new Thread(r1, "Thread_t2");
        t1.start();
        t2.start();

    }
}
结果:t1 t2交替获得锁
Thread_t2获得锁
Thread_t1获得锁
Thread_t2获得锁
Thread_t1获得锁
Thread_t2获得锁
Thread_t1获得锁
Thread_t2获得锁
Thread_t1获得锁
Thread_t2获得锁

Reentrantlock重要方法整理
lock():获得锁,如果锁被占用,则等待
lockInterruptibly():获得锁,但优先响应中断
tryLock():尝试获得锁,如果成功返回true,失败则返回false。该方法不等待,立即返回。
tryLock(long time,TimeUnit unit):在给定时间内尝试获得锁
unlock():释放锁
重入锁的实现要素:
1原子状态:原子状态使用CAS操作来存储当前锁的状态,判断锁是否已经被别的线程持有。
2等待队列:所有没请求到锁的线程,会进入等待队列等待。待有线程释放锁,系统就能从等待队列中唤醒一个线程,继续工作。
3阻塞原语park()和unpark(),用来挂起和恢复线程。没有得到锁的线程将会被挂起。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值