并发模型

悲观锁和乐观锁的理解及如何实现,有哪些实现方式?

悲观锁

悲观锁假设最坏的情况(如果你不锁门,那么捣蛋鬼就会闯入并搞得一团糟),并且只有在确保其他线程不会干扰(通过获取正确的锁)的情况下才能执行下去。

常见实现如独占锁等。

安全性更高,但在中低并发程度下的效率更低。

乐观锁

乐观锁借助冲突检查机制来判断在更新过程中是否存在其他线程的干扰,如果存在,这个操作将失败,并且可以重试(也可以不重试)。

常见实现如CAS等。

部分乐观锁削弱了一致性,但中低并发程度下的效率大大提高。

并发编程

Java中如何创建一个线程

从面相接口的角度上讲,实际上只有一种方法实现Runable接口;但Thread类为线程操作提供了更多的支持,所以通常做法是实现Runable接口,实例化并传入Thread类的构造函数。

  • 继承Thread,覆写run方法

  • 实现Runable接口,覆写run方法

Vector(HashTable)如何实现线程安全

通过synchronized关键字修饰每个方法。

依据synchronized关键字引申出以下问题。

synchronized修饰方法和修饰代码块时有何不同

持有锁的对象不同:

  1. 修饰方法时:this引用的当前实例持有锁

  2. 修饰代码块时:要指定一个对象,该对象持有锁

从而导致二者的意义不同:

  • 同步代码块在锁定的范围上可能比同步方法要小,一般来说锁的范围大小和性能是成反比的。

  • 修饰代码块可以选择对哪个对象加锁,但是修饰方法只能给this对象加锁。

ConcurrentHashMap的如何实现线程安全

ConcurrentHashMap的线程安全实现与HashTable不同:

  • 可以将ConcurrentHashMap理解为,不直接持有一个HashMao,而是用多个Segment代替了一个HashMap。但实际实现的Map部分和HashMap的原理基本相同,对脚标取模来确定table[i]所属段,从而对不同的段获取不同的段锁。

  • 每个Segment持有一个锁,通过分段加锁的方式,既实现了线程安全,又兼顾了性能

Java中有哪些实现并发编程的方法

要从最简单的答起,业界最常用的是重点,有新意就放在最后。

1. synchronized关键字

2. 使用继承自Object类的wait、notify、notifyAll方法

3. 使用线程安全的API和集合类:

  • 使用Vector、HashTable等线程安全的集合类

  • 使用Concurrent包中提供的ConcurrentHashMap、CopyOnWriteArrayList、ConcurrentLinkedQueue等弱一致性的集合类

  • 在Collections类中有多个静态方法,它们可以获取通过同步方法封装非同步集合而得到的集合,如List list = Collection.synchronizedList(new ArrayList())。

4.使用原子变量、volatile变量等

5. 使用Concurrent包中提供的信号量Semaphore、闭锁Latch、栅栏Barrier、交换器Exchanger、Callable&Future、阻塞队列BlockingQueue等.

6. 手动使用Lock实现基于锁的并发控制

7. 手动使用Condition或AQS实现基于条件队列的并发控制

8. 使用CAS和SPIN等实现非阻塞的并发控制

使用不变类

9. 其他并发模型还没有涉及

从而引申出如下问题:

  • ConcurrentHashMap的的实现原理(见前)

  • CopyOnWriteArrayList的复制操作发生在什么时机

  • synchronizedList&Vector的区别

  1. synchronizedList的实现中,synchronized关键字修饰代码块;Vector的实现中修饰方法。

  2. synchronizedList只封装了add、get、remove等代码块,但Iterator却不是同步的,进行遍历时要手动进行同步处理;Vector中对Iterator也进行了加锁。

  3. synchronizedList能够将所有List实现类封装为同步集合,其内部持有的仍然是List的实现类(ArrayList/LinkedList),所以除同步外,几乎只有该实现类和Vector的区别。

synchronized修饰方法和修饰代码块时有何不同(见前)

信号量Semaphore、闭锁Latch、栅栏Barrier、交换器

Exchanger、Callable&Future、阻塞队列BlockingQueue的实现原理

ConcurrentLinkedQueue的插入算法

算法核心可概括为两步:

  • 先检测是否是中间状态(SPIN)

  • 再尝试CAS插入

详细待补充。

参考:

  • CopyOnWriteArrayList与Collections.synchronizedList的性能对比

    https://link.juejin.im/?target=http%3A%2F%2Fblog.csdn.net%2Fyangzl2008%2Farticle%2Fdetails%2F39456817

  • SynchronizedList和Vector的区别

    https://link.juejin.im/?target=http%3A%2F%2Fwww.hollischuang.com%2Farchives%2F498

在java中wait和sleep方法的不同?

最大的不同是在等待时wait会释放锁,而sleep一直持有锁。Wait通常被用于线程间交互,sleep通常被用于暂停执行。

为什么wait, notify 和 notifyAll这些方法不在thread类里面?

主要原因是JAVA提供的锁是对象级的而不是线程级的,每个对象都有锁,通过线程获得。由于wait,notify和notifyAll都是锁级别的操作,所以把他们定义在Object类中因为锁属于对象。

为什么wait和notify方法要在同步块中调用?

Java API强制要求这样做,如果你不这么做,你的代码会抛出IllegalMonitorStateException异常。还有一个原因是为了避免wait和notify之间产生竞态条件。

为什么你应该在循环中检查等待条件?

处于等待状态的线程可能会收到错误警报和伪唤醒,如果不在循环中检查等待条件,程序就会在没有满足结束条件的情况下退出。

Java线程池中submit() 和 execute()方法有什么区别?

两个方法都可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中, 而submit()方法可以返回持有计算结果的Future对象,它定义在ExecutorService接口中,它扩展了Executor接口,其它线程池类像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有这些方法。

volatile 变量和 atomic 变量有什么不同?

Volatile变量可以确保先行关系,即写操作会发生在后续的读操作之前, 但它并不能保证原子性。例如用volatile修饰count变量那么 count++ 操作就不是原子性的。而AtomicInteger类提供的atomic方法可以让这种操作具有原子性如getAndIncrement()方法会原子性的进行增量操作把当前值加一,其它数据类型和引用变量也可以进行相似操作。

为什么Thread类的sleep()和yield ()方法是静态的?

Thread类的sleep()和yield()方法将在当前正在执行的线程上运行。所以在其他处于等待状态的线程上调用这些方法是没有意义的。这就是为什么这些方法是静态的。它们可以在当前正在执行的线程中工作,并避免程序员错误的认为可以在其他非运行线程调用这些方法。

<转>Java 高并发综合的更多相关文章

  1. Java高并发综合

    这篇文章是研一刚入学时写的,今天整理草稿时才被我挖出来.当时混混沌沌的面试,记下来了一些并发的面试问题,很多还没有回答.到现在也学习了不少并发的知识,回过头来看这些问题和当时整理的答案,漏洞百出又十分 ...

  2. 高级java高并发,高性能,分布式,高可用,负载均衡,系统架构实战

    java架构师.集群.高可用.高可扩 展.高性能.高并发.性能优化.Spring boot.Redis.ActiveMQ.Nginx.Mycat.Netty.Jvm大型分布 式项目实战 视频课程包含: ...

  3. Java高并发的常见应对方案

    Java高并发的常见应对方案 一.关于并发我们说的高并发是什么? 在互联网时代,高并发,通常是指,在某个时间点,有很多个访问同时到来. 高并发,通常关心的系统指标与业务指标? QPS:每秒钟查询量,广 ...

  4. 关于Java高并发编程你需要知道的“升段攻略”

    关于Java高并发编程你需要知道的"升段攻略" 基础 Thread对象调用start()方法包含的步骤 通过jvm告诉操作系统创建Thread 操作系统开辟内存并使用Windows ...

  5. [ 高并发]Java高并发编程系列第二篇--线程同步

    高并发,听起来高大上的一个词汇,在身处于互联网潮的社会大趋势下,高并发赋予了更多的传奇色彩.首先,我们可以看到很多招聘中,会提到有高并发项目者优先.高并发,意味着,你的前雇主,有很大的业务层面的需求, ...

  6. 【实战Java高并发程序设计 7】让线程之间互相帮助--SynchronousQueue的实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  7. 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  8. 【实战Java高并发程序设计 5】让普通变量也享受原子操作

    [实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...

  9. 【实战Java高并发程序设计 4】数组也能无锁:AtomicIntegerArray

    除了提供基本数据类型外,JDK还为我们准备了数组等复合结构.当前可用的原子数组有:AtomicIntegerArray.AtomicLongArray和AtomicReferenceArray,分别表 ...

随机推荐

  1. 打包python文件为exe文件(PyInstaller工具使用方法)

    最近做的新浪微博爬虫程序,打算打包成.exe软件以方便使用,网上找到一个很好的打包工具pyinstaller,这里记录一下打包的方法. 一.下载pyinstaller 我使用的版本为PyInstall ...

  2. maven工程导入eclipse后报错

    原因:需要重新部署下tomcat环境 解决方式: 右击->属性:

  3. 2014年第五届蓝桥杯国赛 Log大侠(区间合并+Java递归效率分析)

    1678: Log大侠 java 时间限制: 2 Sec  内存限制: 256 MB提交: 20  解决: 1 题目描述     atm参加了速算训练班,经过刻苦修炼,对以2为底的对数算得飞快,人称L ...

  4. 查看 打包秘钥的 SHA1

    keytool -v -list -keystore C:\Users\XXX\.android\debug.keystore 输入密钥库口令: android android

  5. ASP.NET学习笔记(四)CDOSYS邮件

    使用 CDOSYS 发送电子邮件 CDO (Collaboration Data Objects) 是一项微软的技术,设计目的是用来简化通信程序的创建. CDOSYS 是 ASP 中的内置组件.我们会 ...

  6. GitHub上最火爆!码代码不得不知的所有定律法则

    目录 介绍 定律 阿姆达尔定律 (Amdahl's Law) 布鲁克斯法则 (Brooks's Law) 康威定律 (Conway's Law) 侯世达定律 (Hofstadter's Law) 技术 ...

  7. Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml) - filter(5)

    自定义fieldType时,通常还会用到filter.filter必须跟在tokenizer或其它filter之后.如: <fieldType> <analyzer> < ...

  8. 笔记-JavaWeb学习之旅19

    Redis:redis是一款高性能的NOSQL系列的非关系型数据库 NOSQL: Not Only SQL ,意即"不仅仅是SQL",是一项全新的数据库理念,泛指非关系型数据库 r ...

  9. 双系统更新ubuntu后,启动引导项消失,无法进入windows

    1.打开终端输入命令sudo gedit /etc/default/grub 2.修改GRUB_TIMEOUT="10" 3.输入sudo update-grub( update ...

  10. JS高级学习历程-10

    [面向对象] 面向对象的三大特性:封装.继承.多态 封装:在“类”里边有关键字public.protected.private 对成员进行声明,这样每个成员的访问都会受到不同关键字的限制. 继承:在p ...