zoukankan      html  css  js  c++  java
  • juc的锁

    Synchronized

    1. 概念:
      重量级锁、重入锁、jvm 级别锁
      使用:方法:ACC_SYNCHRONIZED、代码块 monitorentermonitorexit
      jvm 监视器
    2. 范围:方法和代码块(对象锁和类锁):
    • 对于普通同步方法,锁是当前实例对象。 对于静态同步方法,锁是当前类的 Class 对象。 对于同步方法块,锁是 Synchonized
      括号里配置的对象。
    1. 场景:

    资源竞争

    1. Lock&ReentrantLock 写法:
    try {
     lock.lock();
    } finally {
     lock.unlock();
    }
    
    • void lock() 获取锁,调用该方法当前线程将会获取锁,当锁获取后,该方法将返回。
    • void lockInterruptibly() throws InterruptedException 可中断获取锁,与 lock()方法不同之处在于该方
    • 法会响应中断,即在锁的获取过程中可以中断当前线程
    • boolean tryLock() 尝试非阻塞的获取锁,调用该方法立即返回,true 表示获取到锁
    • boolean tryLock(long time,TimeUnit unit) throws InterruptedException 超时获取锁,以下情况会返回:
    • 时间内获取到了锁,时间内被中断,时间到了没有获取到锁。
    • void unlock() 释放锁
    1. 统计:
      java.util.concurrent.locks.ReentrantLock#getHoldCount
      java.util.concurrent.locks.ReentrantLock#getQueuedThreads

    2. Synchronized 和 ReentrantLock 对比:

    • Synchronized:jvm 层级的锁 自动加锁自动释放锁
    • Lock:依赖特殊的 cpu 指令,代码实现、手动加锁和释放锁、Condition(生产消费模式)
    • ReentrantReadWriteLock 读写锁
    • 细粒度问题 ,读是共享的、写是独占的
    • java8 增加了对读写锁的优化:StampedLock
    1. 实例代码
    • static Lock可以锁注当前类 非静态的只能锁住当前类的实例对象
    package com.itcode.锁;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * @author 夏天
     * @date 2020年10月29日 22:32
     */
    public class ReentrantLock01 implements Runnable {
        private static int i = 0;
        static Lock lock = new ReentrantLock();
    
        private void add() {
            lock.lock();
            try {
                for (int i1 = 0; i1 < 5000; i1++) {
                    i++;
                }
            } finally {
                lock.unlock();
            }
        }
    
        @Override
        public void run() {
            add();
        }
    
        public static void main(String[] args) throws InterruptedException {
            for (int j = 0; j < 20; j++) {
                i = 0;
                ReentrantLock01 sync01 = new ReentrantLock01();
                ReentrantLock01 sync02 = new ReentrantLock01();
                Thread t1 = new Thread(sync01);
                Thread t2 = new Thread(sync02);
                t1.start();
                t2.start();
                t1.join();
                t2.join();
                System.out.println(i);
            }
        }
    
    }
    
    

    Lock之tryLock

    使用方法:

    try {
    	if(lock.tryLock());
    } finally {
    	//获取到锁在释放 如果不加条件判断 获取不到锁也会进行释放 会抛出异常IllegalMonitorStateException
    	if (lock.isHeldByCurrentThread()) {
    		lock.unlock();
    	}
    }
    
    1. tryLock()方法是有返回值的,它表示用来尝试获取锁,如果获取成功,则返回true,如果获取失败(即锁已被其他线程获取),则返回false,这个方法无论如何都会立即返回。在拿不到锁时不会一直在那等待。
    1. boolean tryLock(long timeout, TimeUnit unit) :
      参数1 等待时间,参数2 时间单位
      等待指定时间如果还获取不到锁返回false

    实例代码:

    package com.itcode.锁;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    /**
     * @author 夏天
     * @date 2020年10月29日 22:32
     */
    public class ReentrantLock02 implements Runnable {
        private static int i = 0;
        ReentrantLock lock = new ReentrantLock();
    
    
        @Override
        public void run() {
            try {
                if (lock.tryLock(4, TimeUnit.SECONDS)) {
                    System.out.println(Thread.currentThread().getName() + "获取");
                    Thread.sleep(6000);
                } else {
                    System.out.println(Thread.currentThread().getName() + "获取锁失败");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //注意 不加这个会报错 IllegalMonitorStateException 没有锁无法解锁
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
    
        }
    
        public static void main(String[] args) throws InterruptedException {
            ReentrantLock02 reentrantLock02 = new ReentrantLock02();
            Thread t1 = new Thread(reentrantLock02);
            Thread t2 = new Thread(reentrantLock02);
            t1.start();
            t2.start();
            t1.join();
            t2.join();
        }
    }
    
    

    ReentrantReadWriteLock 读写锁

    细粒度问题 ,读是共享的、写是独占的

    package com.itcode.锁;
    
    import java.util.concurrent.*;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    /**
     * @author 夏天
     * @date 2020年10月29日 22:42
     * 可以同时读 上了写锁后就不可以读了
     */
    public class ReadWriterLockTest {
    
        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
        ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
    
        public String query() {
            readLock.lock();
            try {
                Thread.sleep(50);
    
                System.out.println("读数据");
                return "成功";
            } catch (InterruptedException e) {
                e.printStackTrace();
                return "成功";
            } finally {
                readLock.unlock();
            }
        }
    
        public void save() {
            writeLock.lock();
            try {
                System.out.println("保存数据");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                writeLock.unlock();
            }
        }
    
        /**
         * 读50次
         */
        int readCount = 50;
        /**
         * 写5次
         */
        int writeCount = 5;
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            ReadWriterLockTest readWriterLockTest = new ReadWriterLockTest();
            //new Thread(() -> {
            //    while (true) {
            //        readWriterLockTest.query();
            //    }
            //}).start();
            //new Thread(() -> {
            //    while (true) {
            //        try {
            //            readWriterLockTest.save();
            //        } catch (InterruptedException e) {
            //            e.printStackTrace();
            //        }
            //    }
            //}).start();
            CompletableFuture<String> queryFuture = CompletableFuture.supplyAsync(() -> {
                while (readWriterLockTest.readCount-- > 0) {
                    readWriterLockTest.query();
                }
                return "查询完成";
            });
            CompletableFuture<String> saveFuture = CompletableFuture.supplyAsync(() -> {
                while (readWriterLockTest.writeCount-- > 0) {
                    readWriterLockTest.save();
                }
                return "保存完成";
            });
            //等待所有线程结束 无法接受返回值 ,接收返回值使用anyOf
            CompletableFuture.allOf(queryFuture, saveFuture).get();
        }
    }
    
    
  • 相关阅读:
    泛型的内部原理:类型擦除以及类型擦除带来的问题
    内部类访问局部变量的时候,为什么变量必须加上final修饰
    Web 测试经验总结
    故障测试
    智能硬件产品的测试经验总结
    web端测试和移动端测试的区别小记
    MVC模式介绍
    重定向与转发
    MySQL权限管理分配
    pt-heartbeat工具监控MySQL复制延迟
  • 原文地址:https://www.cnblogs.com/idcode/p/13900397.html
Copyright © 2011-2022 走看看