• 55 synchronized 和 ReentrantLock 区别是什么?


    synchronized 和 ReentrantLock 区别是什么?

    答:

    主要区别如下:

    1. ReentrantLock 只适用于代码块锁,而 synchronized 可用于修饰方法、代码块等。

    2. synchronized 竞争锁时会一直等待;ReentrantLock 可以尝试获取锁,并得到获取结果

    3. 超时获取锁的特性:synchronized 获取锁无法设置超时;ReentrantLock 可以设置获取锁的超时时间

    4. synchronized 无法实现公平锁;ReentrantLock 可以满足公平锁,即先等待先获取到锁

    5. synchronized 控制等待和唤醒需要结合加锁对象的 wait() 和 notify()、notifyAll();ReentrantLock 控制等待和唤醒需要结合 Condition 的 await() 和 signal()、signalAll() 方法

    6. synchronized 是 JVM 层面实现的;ReentrantLock 是 JDK 代码层面实现

    7. 便利性:synchronized 在加锁代码块执行完或者出现异常,自动释放锁;ReentrantLock 不会自动释放锁,需要手动在 finally{} 代码块显示释放

    相同点:都可以做到同一线程,同一把锁,可重入代码块。

    原文链接: https://www.cnblogs.com/ConstXiong/p/12014904.html (概念)
    原文链接: https://www.cnblogs.com/jlutiger/p/10548291.html (底层原理)
    原文链接: https://blog.csdn.net/zmx729618/article/details/51594166 (代码示例演示)

    拓展:

    ReentrantLock称为重入锁,位于JUC包的locks,和CountDownLatch、FutureTask一样基于AQS实现。能够实现比synchronized更细粒度的控制,比如控制公平性。此外需要注意,调用lock()之后,必须调用unlock()释放锁。它的性能未必比synchronized高,并且是可重入的。

    在Java 6之后,synchronized性能得到很大提升。主要是因为引入了:

      1:Adaptive spinning(自适应自旋)

      2:Lock Eliminate(锁消除)

      3:Lock Coarsening(锁粗化)

      4:Lightweight Locking(轻量级锁)

      5:Biased Locking(偏向锁)

      6:......

    公平锁与非公平锁

    按照申请锁的顺序来一次获得锁称为公平锁.synchronized的是非公平锁,ReentrantLock可以通过构造函数实现公平锁. new RenentrantLock(boolean fair)

    实例演示

    ReentrantLock 的lock机制有2种,忽略中断锁和响应中断锁,这给我们带来了很大的灵活性。比如:如果A、B两个线程去竞争锁,A线程得到了锁,B线程等待,但是A线程这个时候实在有太多事情要处理,就是一直不返回,B线程可能就会等不及了,想中断自己,不再等待这个锁了,转而处理其他事情。这个时候ReentrantLock就提供了两种机制:

    一、B线程中断自己(或者别的线程中断它),但ReentrantLock 不去响应,让B线程继续等待,你再怎么中断,我全当耳边风(synchronized原语就是如此);

    二、B线程中断自己(或者别的线程中断它),ReentrantLock 处理了这个中断,并且不再等待这个锁的到来,完全放弃。

    请看例子:

    package zmx.multithread.test.reentrantlock;
     
    import java.util.concurrent.locks.ReentrantLock;
     
     
    /**
     * 
     * @author zhangwenchao
     *
     */
     
    public class ReentrantLockTest {
        //是用ReentrantLock,还是用synchronized
    	
        public static boolean useSynchronized = false;
        
        public static void main(String[] args) {
            IBuffer buff = null;
            if(useSynchronized){
                buff = new Buffer();
            }else{
                buff = new BufferInterruptibly();    
            }
            final Writer writer = new Writer(buff);
            final Reader reader = new Reader(buff);
            writer.start();
            reader.start();
            new Thread(new Runnable() {
                public void run() {
                    long start = System.currentTimeMillis();
                    for (;;) {
                        // 等5秒钟去中断读
                        if (System.currentTimeMillis() - start > 5000) {
                            System.out.println("不等了,尝试中断");
                            reader.interrupt();
                            break;
                        }
     
                    }
     
                }
            }).start();
        }
    }
     
    interface IBuffer{
        public void write();
        public void read() throws InterruptedException;
    }
     
    class Buffer implements IBuffer{
        private Object lock;
     
        public Buffer() {
            lock = this;
        }
     
        public void write() {
            synchronized (lock) {
                long startTime = System.currentTimeMillis();
                System.out.println("开始往这个buff写入数据…");
                for (;;)// 模拟要处理很长时间
                {
                    if (System.currentTimeMillis() - startTime > Integer.MAX_VALUE)
                        break;
                }
                System.out.println("终于写完了");
            }
        }
     
        public void read() {
            synchronized (lock) {
                System.out.println("从这个buff读数据");
            }
        }
    }
     
    class BufferInterruptibly implements IBuffer{
     
        private ReentrantLock lock = new ReentrantLock();
     
        public void write() {
            lock.lock();
            try {
                long startTime = System.currentTimeMillis();
                System.out.println("开始往这个buff写入数据…");
                for (;;)// 模拟要处理很长时间
                {
                    if (System.currentTimeMillis() - startTime > Integer.MAX_VALUE)
                        break;
                }
                System.out.println("终于写完了");
            } finally {
                lock.unlock();
            }
        }
     
        public void read() throws InterruptedException{
            lock.lockInterruptibly();// 注意这里,可以响应中断
           // lock.lock();// 注意这里,不可以响应中断
            try {
                System.out.println("从这个buff读数据");
            } finally {
                lock.unlock();
            }
        }
     
    }
     
    class Writer extends Thread {
     
        private IBuffer buff;
     
        public Writer(IBuffer buff) {
            this.buff = buff;
        }
     
        @Override
        public void run() {
            buff.write();
        }
     
    }
     
    class Reader extends Thread {
     
        private IBuffer buff;
     
        public Reader(IBuffer buff) {
            this.buff = buff;
        }
     
        @Override
        public void run() {
     
            try {
                buff.read();
            } catch (InterruptedException e) {
                System.out.println("我不读了");   
            }
     
            System.out.println("读结束");
     
        }
    }
    

     

    1) 如果使用lock.lockInterruptibly();指定可以响应中断,则输出如下:

    开始往这个buff写入数据…
    不等了,尝试中断
    我不读了
    读结束`
    

    则:获取到中断异常,执行中断异常处理程序。
     

    1. 如果使用lock.lock();指定不可以响应中断,则输出如下:
    开始往这个buff写入数据…
    不等了,尝试中断
    

    则:不能获取到中断异常,线程等待。
     

    示例二:

    package zmx.multithread.test.reentrantlock;
     
    import java.util.concurrent.TimeUnit;  
    import java.util.concurrent.locks.Lock;  
    import java.util.concurrent.locks.ReentrantLock;  
      
    public class T2{  
        public static void main(String[] args){    
            Thread i1 = new Thread(new RunIt3());  
            Thread i2 = new Thread(new RunIt3());  
            i1.start();  
            i2.start();  
            i2.interrupt();  //中断
        }  
      }  
     
    class RunIt3 implements Runnable{  
      
        private static Lock lock = new ReentrantLock();  
        public void run(){  
            try{  
                //---------a--------------------------  
                //lock.lock();            
                lock.lockInterruptibly(); 
                //lock.tryLock();
                //lock.tryLock(5,TimeUnit.SECONDS); 
                System.out.println(Thread.currentThread().getName() + " running");  
                TimeUnit.SECONDS.sleep(10);             
                System.out.println(Thread.currentThread().getName() + " finished"); 
                lock.unlock();
                
            }catch (InterruptedException e){  
                System.out.println(Thread.currentThread().getName() + " interrupted");  
      
            }  
      
        }  
    } 
    

     

    如果a处是lock.lock(); 输出: 
    Thread-0 running 
    (这里休眠了10s) 
    Thread-0 finished 
    Thread-1 running 
    Thread-1 interrupted 
    ============================ 
        如果a处是lock.lockInterruptibly();输出: 
    Thread-0 running 
    Thread-1 interrupted 
    (这里休眠了10s) 
    Thread-0 finished 
    
  • 相关阅读:
    .net开源工作流ccflow从表数据数据源导入设置
    驰骋开源的asp.net工作流程引擎java工作流 2015 正文 驰骋工作流引擎ccflow6的功能列表
    app:clean classes Exception
    Android Couldn't load BaiduMapSDK
    android okvolley框架搭建
    compileDebugJavaWithJavac
    android重复的文件复制APK META-INF许可证错误记录
    android listview多视图嵌套多视图
    通讯录笔记
    面试总结
  • 原文地址:https://www.cnblogs.com/ynzj123/p/12897620.html
Copyright © 2020-2023  润新知