4.1 显示锁ReentrantLock的理解,使用示例

目录

有了synchronized为什么还要Lock

lock常用的方法

lock使用的标准代码

ReentrantLock使用示例lock和unlock:

ReentrantLock使用示例tryLock()

ReentrantLock使用示例lock.lockInterruptibly();


有了synchronized为什么还要Lock

  Synchronized ReentrantLock
类型 关键字:修饰方法或者代码块 接口:常用的五个方法
  隐式获取锁,把锁的获取和释放固化了,即先获取再释放

1、能够尝试非阻塞获取锁(tryLock())

2、能够响应中断,被中断时,会跑出中断异常,同时会释放锁

3、能够超时获取锁tryLock(long time, TimeUnit unit)

可重入(原理:线程持有者和计数器) 支持 已经获取到锁的线程,能够再次调用lock()方法获取锁而不被阻塞

公平:先对锁获取的先被满足,效率低

非公平:多个线程不管先后竞争锁

非公平 通过构造函数自定义public ReentrantLock(boolean fair)

 

lock常用的方法

方法名称 描述
void lock(); 获取锁,调用该方法当前线程会获取锁,当获取锁后,从该方法返回
void lockInterruptibly() throws InterruptedException; 可中断地获取锁,和lock()方法的不同之处在于该方法会响应中断,即在锁的获取中可以中断当前线程
boolean tryLock(); 尝试获取锁,调用后回立即返回,获取到锁true,否则返回fasle
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;

1、在超时时间获取锁:true

2、在超时时间内被中断:false

3、超时:false

void unlock(); 释放锁

lock使用的标准代码

lock.lock();
try{
    count++;    
}finally{
    lock.unLock();
}

ReentrantLock使用示例lock和unlock:

两个线程对count自增1000,另一个线程对count自减1000

public class MyReentrantLock {
    int count = 1000;

    public static void main(String[] args) throws InterruptedException {
        MyReentrantLock myReentrantLock = new MyReentrantLock();
        Lock lock = new ReentrantLock();
        new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                lock.lock();
                try {
                    myReentrantLock.count++;
                } finally {
                    lock.unlock();
                }
            }
        }).start();
        new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                lock.lock();
                try {
                    myReentrantLock.count--;
                } finally {
                    lock.unlock();
                }
            }
        }).start();
        //主线程一定要进行休眠,否则可能会得到修改过程中count的值,而不是最终值
        Thread.sleep(1000);
        System.out.println(myReentrantLock.count);
    }
}

结果:1000

ReentrantLock使用示例tryLock()

public static void main(String[] args) throws InterruptedException {
        MyReentrantLock myReentrantLock = new MyReentrantLock();
        Lock lock = new ReentrantLock();
        Thread thread = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    if (lock.tryLock(500, TimeUnit.MILLISECONDS)) {

                        Thread.sleep(100);
                        myReentrantLock.count++;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        });
        thread.start();
        //thread.interrupt();


        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                if (lock.tryLock()) {
                    try {
                        myReentrantLock.count--;
                    } finally {
                        lock.unlock();
                    }
                }

            }
        });
        //thread2.interrupt();
        //主线程一定要进行休眠,否则可能会得到修改过程中count的值,而不是最终值
        Thread.sleep(1000);
        System.out.println(myReentrantLock.count);
    }
}

结果在:1000-1010之间

ReentrantLock使用示例lock.lockInterruptibly();

public class MyReentrantLock {
    int count = 1000;

    public static void main(String[] args) throws InterruptedException {
        MyReentrantLock myReentrantLock = new MyReentrantLock();
        Lock lock = new ReentrantLock();

        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    lock.lockInterruptibly();
                    Thread.sleep(100);
                    myReentrantLock.count--;
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }

        });
        thread2.start();
        Thread.sleep(100);
        thread2.interrupt();
        //主线程一定要进行休眠,否则可能会得到修改过程中count的值,而不是最终值
        Thread.sleep(1200);
        System.out.println(myReentrantLock.count);
    }
}

结果:

java.lang.InterruptedException
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220)
	at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
	at cn.enjoyedu.ch4.MyReentrantLock.lambda$main$0(MyReentrantLock.java:39)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
	at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
	at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
	at cn.enjoyedu.ch4.MyReentrantLock.lambda$main$0(MyReentrantLock.java:45)
	at java.lang.Thread.run(Thread.java:748)
999

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章