乐趣区

关于java:ReenTrantLock和Synchronized

1.jdk 中罕用的独占锁有两种:Synchronized,ReenTrantLock。两种锁在性能上差异不大, 但 ReenTrantLock 手动加锁,解锁,更加灵便,性能更加丰盛

1)独占锁, 可重入锁

public class TestReenTrantLock {static Lock lock = new ReentrantLock(true);

    public static void main(String[] args) {
        // 可重入锁: 一个线程屡次获取同一个对象上的锁。可重入锁的意义之一在于避免死锁 
        实现原理: 当线程获取锁时,jvm 将记录锁的占有者,并将锁中的计数器加 1,同一个线程再次取得锁,计数器再次加 1。未被占用的锁,计数器为 0。当线程退出同步块,计数器值将递加,直到计数器值为 0,锁被开释。其余线程能力取得锁
        独占锁: 一个锁一次只能被一个线程占有
        method();
        method1();

        lock.unlock();
        lock.unlock();}


    public static void method(){lock.lock();
        System.out.println("第一次获取锁");
    }

    public static void method1(){lock.lock();
        System.out.println("第二次获取锁");
    }
}

这里在 method 中获取了 TestReenTrantLock 类锁, 调用 method1 时再一次获取了 TestReenTrantLock 类锁, 这就是可重入锁

2)能够实现偏心锁

public class FairReenTrantLock {

    /**
     * 偏心锁:当锁可用时, 在锁上等待时间最长的线程获取锁的使用权
     * 无参数或为 fasle,为非偏心锁
     * 非偏心锁:随机取得锁的使用权
     */
    static Lock lock = new ReentrantLock(true);

    public static void main(String[] args) {for (int i=0; i<5; i++){new Thread(new ThreadDemo()).start();}
    }


    static class ThreadDemo implements Runnable{public ThreadDemo(){ }

        @Override
        public void run() {
            try {TimeUnit.SECONDS.sleep(2);
            }catch (Exception e){e.printStackTrace();
            }
            for(int i=0; i<2; i++){lock.lock();
                System.out.println("取得锁的线程"+Thread.currentThread().getName());
                lock.unlock();}
        }
    }

}


3)能够响应线程中断

  • 首先理解一下 public void interrupt();(属于 ThreadL 类)
public class TestInterrupt {public static void main(String[] args) throws InterruptedException {Thread testThread = new TestThread();
        testThread.start();
        testThread.interrupt();}

    /*
    * 上面测试的三个办法都会阻塞线程, 如果没有应用这个三个办法,线程会间接走完,* 而且 isInterrupted()为 true
    * 应用了其中一个, 会抛出 InterruptedException,isInterrupted()为 false
    */
    static class TestThread extends Thread {

        @Override
        public void run() {System.out.println("线程开始运行");
            try {//TimeUnit.SECONDS.sleep(5);
                //wait();
                join();}catch (Exception e){System.out.println("线程产生异样"+e);
                System.out.println(Thread.currentThread().isInterrupted());
            }
            System.out.println("线程完结运行");
        }
    }
}
  • 响应中断案例
public class LockInterruptibly {static Lock firstLock = new ReentrantLock();
    static Lock secondLock = new ReentrantLock();

    public static void main(String[] args) {Thread firstthread = new Thread(new ThreadDemo(firstLock,secondLock));
        Thread secondThread = new Thread(new ThreadDemo(secondLock,firstLock));
        firstthread.start();
        secondThread.start();
        firstthread.interrupt();}

    static class ThreadDemo implements Runnable {
        private Lock firstLock;
        private Lock secondLock;

        public ThreadDemo(Lock firstLock,Lock secondLock){
            this.firstLock = firstLock;
            this.secondLock = secondLock;
        }

        // 会中断处于期待的线程, 开释锁,而后另一个线程获取锁, 持续走
        @Override
        public void run() {
            try {firstLock.lockInterruptibly();
                TimeUnit.SECONDS.sleep(1);
                secondLock.lockInterruptibly();}catch (Exception e){e.printStackTrace();
            }finally {firstLock.unlock();
                secondLock.unlock();
                System.out.println(Thread.currentThread().getName()+"失常完结");
            }
        }
    }
}
  • 不响应中断案例
public class TestSynchronized {static Object resource1 = new Object();
    static Object resource2 = new Object();

    public static void main(String[] args) {Thread thread1 = new TestSynchronizedThread(resource1,resource2);
        Thread thread2 = new TestSynchronizedThread(resource2,resource1);

        thread1.start();
        thread2.start();
        thread1.interrupt();// 中断线程,}

    static class TestSynchronizedThread extends Thread {
        Object resource1;
        Object resource2;
        public TestSynchronizedThread(Object resource1,Object resource2){
            this.resource1 = resource1;
            this.resource2 = resource2;
        }

        // 即便跑出异样,也不会中断线程, 两个线程持续相互期待资源,造成死锁
        @Override
        public void run() {synchronized (resource1){System.out.println(Thread.currentThread().getName()+"--111");
                try {TimeUnit.SECONDS.sleep(1);
                    System.out.println(Thread.currentThread().getName()+"--222");
                } catch (InterruptedException e) {System.out.println(Thread.currentThread().getName()+"--333");
                }

                System.out.println(Thread.currentThread().getName()+"--444");
                synchronized (resource2){System.out.println(555);
                }
            }

        }
    }
}

4)获取锁时, 限时期待
5) 利用 condition 实现期待告诉机制,
6)condition 实现阻塞队列

synchronized

退出移动版