
并发编程
小漆同学
一只有梦想的咸鱼!
展开
-
用“等待-通知”机制优化循环等待
前言在上篇已经了解到,破坏占用且等待条件时如果两个锁不满足同时获取的条件下,就用死循环的方式来循环等待。while(!actr.apply(this, target)) ;如果apply操作耗时非常短,并发量冲突不大的情况下,是可以这样做的。但是在现在并发量大,耗时时间长的情况下就不适用了,因为可能需要循环上万次才能获取到锁,太消耗CPU了。为了解决上面循环等待消耗CPU的问题,最好的...原创 2020-02-27 18:43:49 · 546 阅读 · 0 评论 -
一不小心就死锁了,怎么办?
前言在上篇中的银行转账的例子中, 用Account.class作为互斥锁,虽然能保证并发问题,但是用户A、B、C、D,A转B,B转C是串行的,这是由于用锁Account.class将转账操作串行化了,性能就会很低,在现实生活中这两个转账操作是可以并行处理的,所以需要提升性能。向现实世界要答案例如古代,所有的记账都是在账本上操作的,A和B各自有两个账本,A转账给B,需要账员同时看A和B的账本都...原创 2020-02-24 16:07:23 · 530 阅读 · 0 评论 -
互斥锁:如何用一把锁保护多个资源?
前言在上篇中提到,受保护资源和锁之间合理的关联关系应该是N:1的关系,也就是说一把锁可以用来保护多个资源,但是不能用多把锁来保护一个资源。当我们要保护多个资源时,首先要区分这些资源是否存在关联关系。保护没有关联关系的多个资源例如:账户中转账操作、修改密码操作,可以通过分配不同的锁来解决并发问题。class Account { // 锁:保护账户余额 private final O...原创 2020-02-23 21:42:43 · 628 阅读 · 0 评论 -
互斥锁:解决原子性问题
前言什么是原子性?一个或多个操作在CPU执行的过程中不被中断的特性称为原子性。如何解决原子性问题?原子性的问题根源是线程切换,如果能够禁用线程切换就能解决问题。而操作系统做线程切换是依赖CPU中断的,所以禁止CPU发生中断就能够禁止线程切换.在早期单核时代禁用CPU中断是可行的,但并不是适合多核场景。例如‘在32位的CPU上执行long型变量的读写操作,由于long是64位的,在32位C...原创 2020-02-21 16:56:52 · 836 阅读 · 1 评论 -
Java内存模型:看Java如何解决可见性和有序性问题
前言从上篇文中引出了可见性、原子性和一致性是并发编程的Bug之源,这三者在编程领域是一个共性问题,所有的编程语言都会遇到,Java语言在诞生之初就支持多线程,自然也有针对这三者的技术方案,而且在编程语言领域处于领先地位。如何解决其中的可见性和有序性——Java的内存模型什么是Java的内存模型?由上篇文章知道,可见性是由于缓存导致的,有序性是由于编译优化导致的。那我们可以通过禁用缓存和编译...原创 2020-02-19 23:11:47 · 248 阅读 · 0 评论 -
可见性、原子性和有序性问题:并发编程Bug的源头
并发编程幕后的故事随着设备的不断迭代,相应的速度也变得更快。但是在发展的过程中有一个矛盾一直存在,即三者的速度差异。快慢关系:CPU > 内存 > I/O,程序整体的性能取决于最慢的操作,即读写I/O设备,所以单方面的提升CPU性能是无效的。为了合理利用CPU的高性能,平衡三者的速度差异,计算机体系结构、操作系统、编译程序做出了贡献,体现为:CPU增加了缓存,平衡与内存的速度...原创 2020-02-19 17:59:23 · 342 阅读 · 0 评论 -
Java并发编程实战
并发理论基础可见性、原子性和有序性问题:并发编程Bug的源头原创 2020-02-21 16:55:24 · 629 阅读 · 0 评论 -
关键字 synchronized
使用方式public class SynchronizedTest { /** * 同步方法 */ private synchronized void demo1() { // ... } /** * 同步代码 */ private void demo2() { synchron...原创 2019-01-24 14:00:28 · 133 阅读 · 0 评论 -
Java多线程技能
读《Java多线程编程核心技术》原创 2019-04-20 20:09:41 · 173 阅读 · 0 评论 -
对象及变量的并发访问
title: 对象及变量的并发访问categories: Java多线程编程核心技术tags: 多线程time: 2019-04-21 08:36:04synchronized同步方法“非线程安全”会在多个线程中的同一对象的实例变量在并发访问时发生,产生的后果就是“脏读”,即读到的数据其实是被更改过的。“线程安全”就是以获得的实例变量的值是经过同步处理过的,不会出现“脏读”现象。方...原创 2019-04-22 20:22:26 · 240 阅读 · 0 评论 -
线程间通信
类ThreadLocal的使用变量值的共享可以使用public static变量的方式,所有线程都使用同一个public static的变量。而ThreadLocal就是解决每个线程拥有自己单独的一个共享变量。方法get()与nullpublic class ThreadLocalGetNull { private static ThreadLocal threadLocal =...原创 2019-04-23 22:18:02 · 119 阅读 · 0 评论 -
定时器Timer
在JDK库中Timer类主要负责计划任务的功能,也就是在指定的时间开始执行某一任务。Timer类主要设置计划任务,但封装任务的却是TimerTask类。执行计划任务的代码要放到TimerTask的子类中,因为TimerTask是一个抽象类。创建Timer类就是启动一个新线程,但它不是守护线程,它一直在运行。方法schedule(TimerTask task,Date date)的测试方法s...原创 2019-04-24 10:41:41 · 118 阅读 · 0 评论 -
单例模式和多线程
立即加载/饿汉模式立即加载就是在使用类之前已经将对象创建完毕,常见的实现方法就是new实例化。public class MyThread { private static MyThread INSTANCE = new MyThread(); private MyThread() {} public static MyThread getInstance() { ...原创 2019-04-24 11:44:32 · 377 阅读 · 0 评论 -
Lock的使用
使用RentrantLock类在Java多线程中,可以使用synchronized关键字来实现线程之间同步互斥,但在JDK1.5之后加入了RentrantLock类也能达到同样的效果,并且在扩展功能上的也更强大。比如具有嗅探锁定、多路分支通知等功能,在使用上比synchronized更加灵活。实现同步1调用lock加锁,unlock解锁import java.util.concurrent...原创 2019-04-27 11:08:49 · 125 阅读 · 0 评论