Season Peng

我在这里记录着美好


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

并发设计模式

发表于 2020-02-12 | 分类于 并发编程
字数统计: 948

Immutability模式

不变性(Immutability)模式,即对象一旦被创建之后,状态就不再发生变化。我们知道多个线程同时读写同一共享变量会存在并发问题,如果我们把这里的共享变量改为只读,就不会有并发问题。

我们常用的Integer、Long、Double、String等类都使用了该模式,这些类本身和属性都使用final关键字修饰,使得类不能被继承,属性不能被修改。

当我们对这些类进行修改时,实际上是创建一个新的对象并返回,并不会对旧对象进行修改。

如果我们每次修改都创建新对象的话,是不是有点浪费内存了。针对这点,人们又提出享元模式(Flyweight Pattern)。享元模式可以理解为对象池,对于Long、Integer、Short、Byte等包装类,会预先缓存好常用的数据,之后需要使用到该数据就从缓存中拿。例如Long缓存了数字[-128,127],这个对象池在JVM启动时就会创建好。

若final修饰变量a,说明a的引用不可变,但并不约束引用内容的可变性。例如引用的是对象A,那么对象A的属性是否可变不受该final约束。

Copy on Write模式

在Immutability模式中,对只读对象的修改会创建新的对象,这种方法是写时复制(Copy on Write, Cow)。CoW是解决不可变对象写操作的一个方法。

Copy on Write在许多领域都有广泛的应用,例如Linux中的fork()、Redis中的BGSAVE(本质也是fork())、Java中的CopyOnWriteArrayList等。

CoW的缺点是会消耗较多内存,所以在写操作频繁以及数据量较大时不适合使用。

线程本地存储模式

线程本地存储模式是指不共享数据,每个线程有一份自己的数据备份。例如ThreadLocal和局部变量。

Guarded Suspension模式

Guarded Suspension模式本质上是一种等待唤醒机制的实现,典型的实现就是管程。

该模式与Balking模式都是多线程的if版本,区别是该模式会一直等待if条件变为真。

Balking模式

Balking模式是指在多线程之间共享一个状态变量,业务逻辑依赖于这个状态变量的状态:当状态满足某个条件时,执行某个业务逻辑。在Java中实现Balking模式的关键是可见性,可见性可以通过互斥锁和volatile解决。

双重检查的单例模式就是Balking模式的一个应用。

该模式与Guarded Suspension模式都是多线程的if版本,区别是该模式只会判断一次条件,不会等待。

Thread-Per-Message模式

Thread-Per-Message模式,即为每个任务分配一个独立的线程。Thread-Per-Message模式的一个最经典的应用场景是网络编程里服务端的实现,服务端为每个客户端请求创建一个独立的线程。

Work Thread模式

Worker Thread模式可以类比现实世界里车间的工作模式:车间里的工人,有活儿了,大家一起干,没活儿了就聊聊天等着。Worker Thread对应到现实世界里,其实指的就是车间里的工人。

Java中的线程池采用了这种模式。

两阶段终止模式

两阶段终止模式,即将终止过程分成两个阶段。用于优雅地终止线程,其中第一阶段主要是线程T1向线程T2发送终止指令,第二阶段则是线程T2响应指令。

生产者-消费者模式

  • 解耦
  • 异步
  • 平衡生产者、消费者之间的速度差异

并发编程之互斥

发表于 2020-02-08 | 分类于 并发编程
字数统计: 2.2k

并发编程领域可以抽象为3个核心问题:分工、协作、互斥。

本文介绍互斥。

互斥是为了保证程序的正确性,用专业术语叫“线程安全”。并发程序里,当多个线程同时访问同一个共享变量的时候,结果是不确定的。而导致不确定的主要源头是可见性问题、有序性问题和原子性问题,为了解决这三个问题,Java 语言引入了内存模型,内存模型提供了一系列的规则,利用这些规则,我们可以避免可见性问题、有序性问题,但是还不足以完全解决线程安全问题。解决线程安全问题的核心方案还是互斥。所谓互斥,指的是同一时刻,只允许一个线程访问共享变量。加锁方案有Java语言里的synchronized、并发包里的各种Lock。无锁方案有Java并发包里提供的原子类。除此之外,还有一些其他的方案,原理是不共享变量或者变量只允许读。这方面,Java提供了Thread Local和final关键字,还有一种Copy-on-write的模式。

阅读全文 »

分布式事务

发表于 2020-01-25 | 分类于 分布式
字数统计: 454

单数据源的一致性可以使用单机事务来保证,多数据源的一致性需要使用分布式事务来保证。

ACID(A原子性、C一致性、I隔离性、D持久性)是单机事务的特性。

CAP、BASE理论是分布式领域的理论。

阅读全文 »

并发编程之分工

发表于 2020-01-21 | 分类于 并发编程
字数统计: 2.7k

并发编程领域可以抽象为3个核心问题:分工、协作、互斥。

本文介绍分工。

所谓分工,类似于现实中完成一个项目,项目经理要拆分任务,安排合适的成员去完成。在并发编程领域,线程就是成员,分工直接决定了并发程序的性能。Java并发包里的Executor、Fork/Join、Future本质上都是一种分工方法。除此之外,并发编程领域还总结了一些设计模式,基本上都是和分工方法相关的,例如生产者-消费者、Thread-Per-Message、Worker Thread模式等都是用来指导如何分工的。

阅读全文 »

Mybatis数据源与连接池

发表于 2020-01-11 | 分类于 Mybatis
字数统计: 776

对于ORM(Object Relational Mapping)框架而言,数据源的组织是一个非常重要的一部分,这直接影响到框架的性能问题。本文将通过对MyBatis框架的数据源结构进行详尽的分析,并且深入解析MyBatis的连接池。

本文首先会讲述MyBatis的数据源的分类,然后会介绍数据源是如何加载和使用的。紧接着将分类介绍UNPOOLED、POOLED和JNDI类型的数据源组织;期间我们会重点讲解POOLED类型的数据源和其实现的连接池原理。

阅读全文 »

CopyOnWrite

发表于 2020-01-04 | 分类于 并发设计模式
字数统计: 932

写时复制(Copy On Write,CoW)是一种计算机程序设计领域的优化策略。核心思想是,多个调用者同时请求相同资源时,他们会共同获得相同的指针指向相同的资源。直到某个调用者试图修改资源的内容时,系统才会真正复制一份给该调用者只读同一块资源,而其他调用者所见到的最初的资源仍然保持不变。之后根据策略的不同,复制出的资源可以覆盖旧资源,也可以仅供写资源的调用者使用。

阅读全文 »

草稿

发表于 2020-01-01 | 分类于 草稿
字数统计: 2.4k

理论上,TCP滑动窗口大小设置为带宽*单向时延*2,乘以2的原因是可以充分利用信道。

阅读全文 »

基于Redis的分布式锁

发表于 2019-12-30 | 分类于 Redis
字数统计: 663

基于Redis的分布式锁

阅读全文 »

MySQL

发表于 2019-12-26 | 分类于 数据库
字数统计: 872

MySQL

三种常见索引:

  1. 哈希表:适合等值查询,不适合区间查询;
  2. 有序数组:使用二分法查询等值和区间值,复杂度为O(logn),但只适合静态数据,不再修改的数据;
  3. 树:Innodb的索引采用B+树,是一个N叉树,这里N大约为1200.
阅读全文 »

Redis

发表于 2019-12-26 | 分类于 Redis
字数统计: 1.6k

Redis

  1. 字符串:int、raw、embstr
  2. 列表:ziplist和linkedlist
  3. 哈希表:ziplist和hashtable
  4. 集合:intset和hashtable
  5. 有序集合:ziplist和skiplist

ziplist是一种经过特殊编码的双向链表,不同于普通的双向链表,ziplist存储在一块连续的内存中。ziplist的特殊编码节省了数据所占用的内存。ziplist的每个数据项上都保存有本项的数据长度和上一项的数据长度。这样可以通过指针的运算跳到上一个或者下一个数据项。

阅读全文 »
12…5

Season Peng

45 日志
21 分类
61 标签
© 2014 — 2020 Season Peng
由 Hexo 强力驱动
|
主题 — NexT.Mist