1、锁

当一个共享资源被多方访问时为了避免发生冲突而施加的一种机制

2、乐观锁和悲观锁

Java中锁在宏观分为乐观锁和悲观锁

乐观锁:是一种乐观思想,认为多读少写,一般情况下数据在修改时不会出现冲突,所以在数据访问之前不会加锁,只是在数据提交更改时,才会对数据进行检测

适用场景:比较适合读取操作比较频繁的场景,如果出现大量的写入操作,数据发生冲突的可能性就会增大,为了保证数据的一致性,应用层需要不断的重新获取数据,这样会增加大量的查询操作,降低了系统的吞吐量

乐观锁实现:大部分都是通过 CAS(Compare And Swap,比较并交换)操作实现的,CAS 是一个多线程同步的原子指令,CAS 操作包含三个重要的信息,即内存位置、预期原值和新值。如果内存位置的值和预期的原值相等的话,那么就可以把该位置的值更新为新值,否则不做任何修改,Java从5.0开始引入了对CAS的支持,与之对应的是java.util.concurrent.atomic 包下的AtomicInteger、AtomicReference等类,它们提供了基于CAS的读写操作和并发环境下的内存可见性

悲观锁:是一种是悲观思想,认为写多,遇到并发写的可能性高数据,对外界的修改采取保守策略,它认为线程很容易会把数据修改掉,因此在整个数据被修改的过程中都会采取锁定状态,直到一个线程使用完,其他线程才可以继续使用

悲观锁实现:synchronized关键字、Lock的实现类

适用场景:比较适合写入操作比较频繁的场景,如果出现大量的读取操作,每次读取的时候都会进行加锁,这样会增加大量的锁的开销,降低了系统的吞吐量

3、独占锁和共享锁

独占锁:属于悲观锁,独占锁锁定的资源只允许进行锁定操作的程序使用,其它任何对它的操作均不会被接受,synchronized和ReentrantLock都是独占锁的实现

共享锁:属于乐观锁,共享锁锁定的资源可以被其它用户读取,但其它用户不能修改它,的读锁是可以被共享的,但是它的写锁确每次只能被独占,ReadWriteLock接口是共享锁的实现

4、可重入锁

可重入锁也叫递归锁,指的是同一个线程,如果外面的函数拥有此锁之后,内层的函数也可以继续获取该锁。在 Java 语言中 ReentrantLock 和 synchronized 都是可重入锁,

5、死锁

多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进

产生条件:互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用

       请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放

     不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放

        环路等待条件:在发生死锁时,必然存在一个进程--资源的环形链

避免方法:资源一次性分配:一次性分配所有资源,这样就不会再有请求了:(破坏请求条件)

       只要有一个资源得不到分配,也不给这个进程分配其他的资源:(破坏请保持条件)

     可剥夺资源:即当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源(破坏不可剥夺条件)

        资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)

解除死锁:剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态

        撤消进程:可以直接撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用,死锁状态.消除为止;所谓代价是指优先级、运行代价、进程的重要性和价值等

死锁检测:Jstack命令、JConsole工具

6、公平锁、非公平锁

公平锁:线程需要按照请求的顺序来获得锁

非公平锁:允许“插队”的情况存在,程在发送请求的同时该锁的状态恰好变成了可用,那么此线程就可以跳过队列中所有排队的线程直接拥有该锁,ReentrantLock、synchronized 默认都是非公平锁的实现

公平锁由于有挂起和恢复所以存在一定的开销,性能不如非公平锁

7、volatile关键字、synchronized、ReentrantLock、ReadWriteLock、Lock接口

volatile关键字:

volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取

volatile仅能使用在变量级别

volatile仅能实现变量的修改可见性,不能保证原子性

volatile不会造成线程的阻塞

volatile标记的变量不会被编译器优化

synchronized:

synchronized是通过 JVM 隐式实现的,synchronized 只允许同一时刻只有一个线程操作资源

synchronized是和if、else、for、while一样的关键字

synchronized的锁可重入、不可中断、非公平

synchronized是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住

synchronized可以使用在变量、方法、和类级别的

synchronized可以保证变量的修改可见性和原子性

synchronized可能会造成线程的阻塞

synchronized标记的变量可以被编译器优化

synchronized操作的是对象头中mark word

synchronized锁适合代码少量的同步问题

ReentrantLock:

ReentrantLock是类,实现Lock接口,可以被继承、可以有方法、可以有各种各样的类变量,基于 AQS(Abstract Queued Synchronizer,队列同步器)实现的,它默认是通过非公平锁实现的,在它的内部有一个 state 的状态字段用于表示锁是否被占用,如果是 0 则表示锁未被占用,此时线程就可以把 state 改为 1,并成功获得锁,而其他未获得锁的线程只能去排队等待获取锁资源

ReentrantLock需要手动加锁和释放锁,如果忘记释放锁,则会造成资源被永久占用

ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁

ReentrantLock可以获取各种锁的信息

ReentrantLock可以灵活地实现多路通知

ReentrantLock底层调用的是Unsafe的park方法加锁

// 非公平锁
public ReentrantLock() {
sync = new NonfairSync();
} //可以设置为公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
} //通过lock()方法加锁,unlock() 方法解锁,可以知道当前是否获得锁

ReadWriteLock:

ReadWriteLock是一个接口,主要有两个方法,readLock()和writeLock()

ReadWriteLock需要通过实现读锁和写锁两个方法来用

读锁可以在没有写锁的时候被多个线程同时持有,写锁是独占的(排他的)

public interface ReadWriteLock {

    Lock readLock();

    Lock writeLock();
}

Lock接口:

Lock代表实现类是ReentrantLock(可重入锁),支持语义不同(重入、公平等)的锁规则,可以在非阻塞式结构的上下文(包括 hand-over-hand 和锁重排算法)中使用这些规则

Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁

Lock锁可重入、可判断、可公平(两者皆可)

Lock锁适合大量同步的代码的同步问题

public interface Lock {
// 获取锁
void lock();
// 如果当前线程未被中断,则获取锁,可以响应中断
void lockInterruptibly() throws InterruptedException;
// 返回绑定到此 Lock 实例的新 Condition 实例
boolean tryLock();
// 仅在调用时锁为空闲状态才获取该锁,可以响应中断
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
// 如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁
void unlock();
// 释放锁
Condition newCondition();
}

Java基础——锁的更多相关文章

  1. java基础 - 锁

    ------------------------ 参考: https://www.cnblogs.com/hustzzl/p/9343797.html https://blog.csdn.net/qq ...

  2. JAVA基础再回首(二十五)——Lock锁的使用、死锁问题、多线程生产者和消费者、线程池、匿名内部类使用多线程、定时器、面试题

    JAVA基础再回首(二十五)--Lock锁的使用.死锁问题.多线程生产者和消费者.线程池.匿名内部类使用多线程.定时器.面试题 版权声明:转载必须注明本文转自程序猿杜鹏程的博客:http://blog ...

  3. Java基础教程:多线程杂谈——双重检查锁与Volatile

    Java基础教程:多线程杂谈——双重检查锁与Volatile 双重检查锁 有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化.此时程序员可能会采用延迟初始化.但要正确实 ...

  4. 并发王者课-铂金1:探本溯源-为何说Lock接口是Java中锁的基础

    欢迎来到<并发王者课>,本文是该系列文章中的第14篇. 在黄金系列中,我们介绍了并发中一些问题,比如死锁.活锁.线程饥饿等问题.在并发编程中,这些问题无疑都是需要解决的.所以,在铂金系列文 ...

  5. [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

    如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html   谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...

  6. 最适合作为Java基础面试题之Singleton模式

    看似只是最简单的一种设计模式,可细细挖掘,static.synchronized.volatile关键字.内部类.对象克隆.序列化.枚举类型.反射和类加载机制等基础却又不易理解透彻的Java知识纷纷呼 ...

  7. Java基础加强之多线程篇(线程创建与终止、互斥、通信、本地变量)

    线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...

  8. Java基础应用

    Java集合类解析 List.Map.Set三个接口,存取元素时,各有什么特点? List 以特定次序来持有元素,可有重复元素.Set 无法拥有重复元素,内部排序.Map 保存key-value值,v ...

  9. Java基础常见英语词汇

    Java基础常见英语词汇(共70个) ['ɔbdʒekt] ['ɔ:rientid]导向的                             ['prəʊɡræmɪŋ]编程 OO: object ...

随机推荐

  1. Python测试函数运行时间

    import time import datetime # 测试函数运行时间 def cal_time(fn): """计算性能的修饰器""" ...

  2. 同事跳槽阿里P7,甩我一份微服务架构设计模式文档,看完我也去

    给所有微服务架构开发者的忠告,我想对你们说: 第一,要记住微服务不是解决所有问题的万能“银弹”. 第二,编写整洁的代码和使用自动化测试至关重要,因为这是现代软件开发的基础. 第三,关注微服务的本质,即 ...

  3. Flutter —布局系统概述

    老孟导读:此篇文章非常详细的讲解了 Flutter 布局系统的工作原理. 翻译自:https://itnext.io/flutter-layout-system-overview-c70bbe9ba9 ...

  4. Java-学习日记(100 == 100为true,1000 == 1000却为false?)

    Integer底层设计 100 == 100为true,1000 == 1000却为false? 之前也写过String的==与equals的注意点,这次写下Integer的底层设计,不妨先运行下下面 ...

  5. nginx如何限制并发连接请求数?

    简介 限制并发连接数的模块为:http_limit_conn_module,地址:http://nginx.org/en/docs/http/ngx_http_limit_conn_module.ht ...

  6. 【jmespath】—3. 进阶 Object Projections

    继续,来看Object Projections. 一.Object Projections 上面说的是列表投影,只适用于列表.那么对于json对象,可以用对象投影. 投影最终返回的仍然是个列表,只不过 ...

  7. jkd1.8 stream

    目录 Stream 创建流 通过集合创建,例如Map (常用) 通过数组方式创建 通过Stream静态方法创建 中间操作 筛选和切片 filter limit skip distinct 映射 map ...

  8. 深入了解Netty【一】BIO、NIO、AIO简单介绍

    引言 在Java中提供了三种IO模型:BIO.NIO.AIO,模型的选择决定了程序通信的性能. 1.1.使用场景 BIO BIO适用于连接数比较小的应用,这种IO模型对服务器资源要求比较高. NIO ...

  9. 2020重新出发,NOSQL,Redis主从复制

    Redis主从复制 尽管 Redis 的性能很好,但是有时候依旧满足不了应用的需要,比如过多的用户进入主页,导致 Redis 被频繁访问,此时就存在大量的读操作. 对于一些热门网站的某个时刻(比如促销 ...

  10. 无法从NVIDA官网下载安装CUDA安装包?NVIDA官网怎么了?

    最近几天由于不知名的原因,导致很多人无法从官网下载NVIDA的CUDA安装包,下载时,浏览器提示此文件可能危害你的计算机,选择保留下载下来也只是一个42字节的exe文件 双击进行安装又出现以下问题: ...