zoukankan      html  css  js  c++  java
  • ReentrantLock示例说明

    1、ReentrantLock锁

    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Test_01 {
        Lock lock = new ReentrantLock();
    
        public static void main(String[] args) {
            final Test_01 t = new Test_01();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    t.m1();
                }
            }).start();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            new Thread(new Runnable() {
                @Override
                public void run() {
                    t.m2();
                }
            }).start();
        }
    
        void m1() {
            try {
                lock.lock(); // 加锁
                for (int i = 0; i < 10; i++) {
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println("m1() method " + i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock(); // 解锁
            }
        }
    
        void m2() {
            lock.lock();
            System.out.println("m2() method");
            lock.unlock();
        }
    }

      结果:

    m1() method 0
    m1() method 1
    m1() method 2
    m1() method 3
    m1() method 4
    m1() method 5
    m1() method 6
    m1() method 7
    m1() method 8
    m1() method 9
    m2() method

    2、ReentrantLock尝试锁

    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Test_02 {
        Lock lock = new ReentrantLock();
    
        public static void main(String[] args) {
            final Test_02 t = new Test_02();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    t.m1();
                }
            }).start();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            new Thread(new Runnable() {
                @Override
                public void run() {
                    t.m2();
                }
            }).start();
        }
    
        void m1() {
            try {
                lock.lock();
                for (int i = 0; i < 10; i++) {
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println("m1() method " + i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        void m2() {
            boolean isLocked = false;
            try {
                // 尝试锁, 如果有锁,无法获取锁标记,返回false。
                // 如果获取锁标记,返回true
                // isLocked = lock.tryLock();
    
                // 阻塞尝试锁,阻塞参数代表的时长,尝试获取锁标记。
                // 如果超时,不等待。直接返回。
                isLocked = lock.tryLock(5, TimeUnit.SECONDS);
    
                if (isLocked) {
                    System.out.println("m2() method synchronized");
                } else {
                    System.out.println("m2() method unsynchronized");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (isLocked) {
                    // 尝试锁在解除锁标记的时候,一定要判断是否获取到锁标记。
                    // 如果当前线程没有获取到锁标记,会抛出异常。
                    lock.unlock();
                }
            }
        }
    }

      结果:

    m1() method 0
    m1() method 1
    m1() method 2
    m1() method 3
    m1() method 4
    m2() method unsynchronized
    m1() method 5
    m1() method 6
    m1() method 7
    m1() method 8
    m1() method 9

    3、ReentrantLock可打断锁

    /**
     * 可打断
     * <p>
     * 阻塞状态: 包括普通阻塞,等待队列,锁池队列。
     * 普通阻塞: sleep(10000), 可以被打断。调用thread.interrupt()方法,可以打断阻塞状态,抛出异常。
     * 等待队列: wait()方法被调用,也是一种阻塞状态,只能由notify唤醒。无法打断
     * 锁池队列: 无法获取锁标记。不是所有的锁池队列都可被打断。
     * 使用ReentrantLock的lock方法,获取锁标记的时候,如果需要阻塞等待锁标记,无法被打断。
     * 使用ReentrantLock的lockInterruptibly方法,获取锁标记的时候,如果需要阻塞等待,可以被打断。
     */
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Test_03 {
        Lock lock = new ReentrantLock();
    
        public static void main(String[] args) {
            final Test_03 t = new Test_03();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    t.m1();
                }
            }).start();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Thread t2 = new Thread(new Runnable() {
                @Override
                public void run() {
                    t.m2();
                }
            });
            t2.start();
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            t2.interrupt();// 打断线程休眠。非正常结束阻塞状态的线程,都会抛出异常。
        }
    
        void m1() {
            try {
                lock.lock();
                for (int i = 0; i < 5; i++) {
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println("m1() method " + i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    
        void m2() {
            try {
                lock.lockInterruptibly(); // 可尝试打断,阻塞等待锁。可以被其他的线程打断阻塞状态
                System.out.println("m2() method");
            } catch (InterruptedException e) {
                System.out.println("m2() method interrupted");
            } finally {
                try {
                    lock.unlock();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

      结果:

    m1() method 0
    m1() method 1
    java.lang.IllegalMonitorStateException
    m2() method interrupted
        at java.base/java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:149)
        at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1300)
        at java.base/java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:439)
        at concurrent.t03.Test_03.m2(Test_03.java:72)
        at concurrent.t03.Test_03$2.run(Test_03.java:37)
        at java.base/java.lang.Thread.run(Thread.java:844)
    m1() method 2
    m1() method 3
    m1() method 4

    4、ReentrantLock公平锁

    /*
     *在公平的锁上,线程按照他们发出请求的顺序获取锁,但在非公平锁上,则允许‘插队’:当一个线程请求非公平锁时,如果在发出请求的同时该锁变成可用状态,那么这个线程会跳过队列中所有的等待线程而获得锁。
    非公平的ReentrantLock 并不提倡插队行为,但是无法防止某个线程在合适的时候进行插队。
     *在公平的锁中,如果有另一个线程持有锁或者有其他线程在等待队列中等待这个所,那么新发出的请求的线程将被放入到队列中。而非公平锁上,只有当锁被某个线程持有时,新发出请求的线程才会被放入队列中。
     *非公平锁性能高于公平锁性能的原因:
     *在恢复一个被挂起的线程与该线程真正运行之间存在着严重的延迟。
     *假设线程A持有一个锁,并且线程B请求这个锁。由于锁被A持有,因此B将被挂起。当A释放锁时,B将被唤醒,因此B会再次尝试获取这个锁。与此同时,如果线程C也请求这个锁,那么C很可能会在B被完全唤醒之前获得、使用以及释放这个锁。这样就是一种双赢的局面:B获得锁的时刻并没有推迟,C更早的获得了锁,并且吞吐量也提高了。
     *当持有锁的时间相对较长或者请求锁的平均时间间隔较长,应该使用公平锁。在这些情况下,插队带来的吞吐量提升(当锁处于可用状态时,线程却还处于被唤醒的过程中)可能不会出现。
     **/
    import java.util.concurrent.locks.ReentrantLock;
    
    public class Test_04 {
    
        public static void main(String[] args) {
            TestReentrantlock t = new TestReentrantlock();
            //TestSync t = new TestSync();
            Thread t1 = new Thread(t);
            Thread t2 = new Thread(t);
            t1.start();
            t2.start();
        }
    }
    
    class TestReentrantlock extends Thread {
        // 定义一个公平锁
        private static ReentrantLock lock = new ReentrantLock(true);
    
        public void run() {
            for (int i = 0; i < 5; i++) {
                lock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() + " get lock in TestReentrantLock");
                } finally {
                    lock.unlock();
                }
            }
        }
    
    }
    
    class TestSync extends Thread {
        public void run() {
            for (int i = 0; i < 5; i++) {
                synchronized (this) {
                    System.out.println(Thread.currentThread().getName() + " get lock in TestSync");
                }
            }
        }
    }

      结果(ReentrantLock两种都与可能,但是TestSync只可能出现后一种):

    Thread-2 get lock in TestReentrantlock
    Thread-2 get lock in TestReentrantlock
    Thread-2 get lock in TestReentrantlock
    Thread-2 get lock in TestReentrantlock
    Thread-2 get lock in TestReentrantlock
    Thread-1 get lock in TestReentrantlock
    Thread-1 get lock in TestReentrantlock
    Thread-1 get lock in TestReentrantlock
    Thread-1 get lock in TestReentrantlock
    Thread-1 get lock in TestReentrantlock
    Thread-1 get lock in TestReentrantlock
    Thread-1 get lock in TestReentrantlock
    Thread-1 get lock in TestReentrantlock
    Thread-1 get lock in TestReentrantlock
    Thread-1 get lock in TestReentrantlock
    Thread-2 get lock in TestReentrantlock
    Thread-2 get lock in TestReentrantlock
    Thread-2 get lock in TestReentrantlock
    Thread-2 get lock in TestReentrantlock
    Thread-2 get lock in TestReentrantlock
  • 相关阅读:
    作业3
    字符串的应用
    java类与对象
    作业
    水仙花数
    java例
    读书笔记(构建之法-11.19)
    补psp进度(11月4号-9号)
    PSP进度(11~16)
    团队项目-约跑软件需求规格说明书
  • 原文地址:https://www.cnblogs.com/jing99/p/10694108.html
Copyright © 2011-2022 走看看