博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java多线程(11) - 多线程 - 锁详解:重入锁、公平锁、非公平锁、读写锁、不可重入锁、自旋锁、独享锁、共享锁、互斥锁、悲观锁、乐观锁、分段锁、偏向锁、轻量级锁、重量级锁、CAS算法原理
阅读量:4164 次
发布时间:2019-05-26

本文共 3965 字,大约阅读时间需要 13 分钟。

      重入锁:在需要进行同步的代码上加上锁定,但不要忘记最后一定要释放,不然会造成永远无法释放,其他线程永远无法进来

      公平锁:多个线程按照先后申请顺序获得锁。

      非公平锁:多个线程获取锁的顺序并不是按照申请锁的顺序,可能按照CPU获取的先后优先获取锁,有可能造成优先级翻转或饥饿的现象。

/**

 * 重入锁,必须要手动释放

 */

public class L01ReentrantLock {

    public static void main(String[] args) {

         ReentrantClass reentrantClass = new ReentrantClass();

        

         new Thread(new Runnable() {

             @Override

             public void run() {

                  reentrantClass.method1();

                  reentrantClass.method2();

             }

         },"t1").start();

        

         new Thread(new Runnable() {

             @Override

             public void run() {

                  reentrantClass.method1();

                  reentrantClass.method2();

             }

         },"t2").start();

    }

}

class ReentrantClass {

    //重入锁,必须要手动释放,默认非公平锁(false),即按照CPU执行权

    private ReentrantLock reentrantLock = new ReentrantLock();

   

    //公平锁,先进先处理

//  private ReentrantLock reentrantLock = new ReentrantLock(true);

   

    public void method1() {

         reentrantLock.lock();

         try {

             System.out.println(Thread.currentThread().getName() + "method1");

             Thread.sleep(2000);

             System.out.println(Thread.currentThread().getName() + "method1 end");

         } catch (InterruptedException e) {

             e.printStackTrace();

         }finally {

             reentrantLock.unlock();

         }

    }

   

    public void method2() {

         reentrantLock.lock();

         try {

             System.out.println(Thread.currentThread().getName() + "method2");

             Thread.sleep(1000);

             System.out.println(Thread.currentThread().getName() + "method2 end");

         } catch (InterruptedException e) {

             e.printStackTrace();

         }finally {

             reentrantLock.unlock();

         }

    }

}

 

读写锁:就是实现读写分离的锁,在高并发访问下,尤其是读多写少的情况下,性能高于重入锁。本质就是分成2个锁,读锁可以在多线程并发下访问,但写锁只能一个个的顺序访问。

读读共享、写写互斥、读写互斥。

/**

 * 读写锁:读读共享、读写互斥、写写互斥

 */

public class L02ReentrantReadWriteLock {

    public static void main(String[] args) {

         ReadWriteTest readWriteTest = new ReadWriteTest();

        

         Thread t1 = new Thread(new Runnable() {

             @Override

             public void run() {

                  readWriteTest.read();

             }

         },"t1");

 

         Thread t2 = new Thread(new Runnable() {

             @Override

             public void run() {

                  readWriteTest.read();

             }

         },"t2");

        

         Thread t3 = new Thread(new Runnable() {

             @Override

             public void run() {

                  readWriteTest.read();

             }

         },"t3");

        

         Thread t4 = new Thread(new Runnable() {

             @Override

             public void run() {

                  readWriteTest.write();

             }

         },"t4");

        

         Thread t5 = new Thread(new Runnable() {

             @Override

             public void run() {

                  readWriteTest.write();

             }

         },"t5");

        

//       t1.start();

//       t2.start();

        

         t3.start();

         t4.start();

         t5.start();

        

    }

}

class ReadWriteTest {

   

    //读写锁:读读共享、读写互斥、写写互斥

    private ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();

   

    //读锁

    private ReadLock readLock = readWriteLock.readLock();

   

    //写锁

    private WriteLock writeLock = readWriteLock.writeLock();

   

    public void read() {

         readLock.lock();

         try {

             System.out.println(Thread.currentThread().getName() + "read");

             Thread.sleep(2000);

             System.out.println(Thread.currentThread().getName() + "read end");

         } catch (InterruptedException e) {

             e.printStackTrace();

         }finally {

             readLock.unlock();

         }

    }

   

    public void write() {

         writeLock.lock();

         try {

             System.out.println(Thread.currentThread().getName() + "write");

             Thread.sleep(3000);

             System.out.println(Thread.currentThread().getName() + "write end");

         } catch (InterruptedException e) {

             e.printStackTrace();

         }finally {

             writeLock.unlock();

         }

    }

}

 

      不可重入锁:当前线程执行某个方法以及获取了该锁,那么在方法中尝试再次获取锁,就会获取不到被阻塞。

自旋锁:但一个线程在获取锁的时候,如果锁已经被其他线程获取,那么该线程将循环等待,然后不断判断锁是否能够被获取,直到获取到锁才会退出循环。

独享锁:锁每一次只能被一个线程持有。

共享锁:该锁可以被多个线程持有,读写锁中的读锁就是如此。

互斥锁:在访问共享资源之前对其进行加锁操作,在访问完成之后进行解锁操作。保证只有一个线程能够访问被互斥锁保护的资源。

悲观锁:每次都假设最差的情况,如数据库的表锁,行锁都鞥都是在做操作之前就加上独享锁,其他线程无法访问。

乐观锁:假设最好的情况,每次去拿数据都不会认为别人修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有更新这个数据,可以用版本号(mongodb、ES)或CAS算法实现,这样做可以提高吞吐量。

分段锁:是一种锁的设计,并不是具体的一个锁,如ConcurrentHashMap,其并发就是通过分段锁的形式实现的并发操作。加锁的机制是基于粒度更小的分段锁。

偏向锁:同步代码一直被一个线程访问,该线程自动获得锁,降低锁的代价。

轻量级锁:在偏向锁的基础上,还有其他线程访问,其他线程会自旋的形式尝试获取到锁,不会阻塞,提高性能,而偏向锁就升级为轻量级锁。

重量级锁:在轻量级锁的基础上,其他线程在自旋的情况下,不会一直下去,而是自旋到一定的次数,还没有获取到锁,就会进入阻塞。膨胀到一定程度,该锁会升级为重量级锁,其他线程进来就直接阻塞,性能降低。

      CAS算法:就是在Atomic系列类讲过的,全称为Compare and Swap(比较并交换),是一种有名的无锁算法。无锁编程,即不使用所的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量同步,所以也叫非阻塞同步。

      CAS算法原理:更新一个变量时,只有当变量的预期旧值A和内存地址V当中的实际值相同时,才回将内存地址V对应的值修改为新值B,否则不会执行任何操作。一般情况下是一个自旋的操作,即不断重试。

      锁优化建议:避免死锁、减少锁持有的时间、减少锁的粒度、锁的分离、尽量无锁操作,如原子操作(Atomic系列类)、volatile关键字。

 

转载地址:http://bmmxi.baihongyu.com/

你可能感兴趣的文章
Java多线程(10) - 多线程 - CountDownLatch、CyclicBarrier、Semaphore使用示例详解
查看>>
Java多线程(11) - 多线程 - 锁详解:重入锁、公平锁、非公平锁、读写锁、不可重入锁、自旋锁、独享锁、共享锁、互斥锁、悲观锁、乐观锁、分段锁、偏向锁、轻量级锁、重量级锁、CAS算法原理
查看>>
Java网络编程(10) - Netty网络编程常见问题与疑问
查看>>
设置Django连接到Google Cloud SQL(MYSQL)
查看>>
爬虫: 基于Node.js的强大爬虫,能直接发布抓取的文章哦
查看>>
Django学习笔记 扩展User模型
查看>>
Django资料总结
查看>>
Android进阶系列-发布项目到Jcenter
查看>>
基于Zxing的二维码扫描解析库——ZxingPlus
查看>>
算法入门-程序设计入门
查看>>
java数据结构-数据结构的概述
查看>>
java -Math常用方法
查看>>
Android进阶系列-手写数据库框架
查看>>
算法入门-循环结构程序设计
查看>>
算法入门-数组和字符串
查看>>
Android进阶系列-手写高并发网络访问框架
查看>>
Java基础之线程安全基本数据类型
查看>>
Android进阶系列-手写高并发图片加载框架
查看>>
Android基础系列-大纲汇总
查看>>
Android测试系列(一)-Monkey
查看>>