技术博客-并发并行

Posted by xiezg247 on January 1, 2016

并发

Java 并发

多线程

线程安全

一致性、事务

事务 ACID 特性

事务的隔离级别

  • 未提交读:一个事务可以读取另一个未提交的数据,容易出现脏读的情况。
  • 读提交:一个事务等另外一个事务提交之后才可以读取数据,但会出现不可重复读的情况(多次读取的数据不一致),读取过程中出现UPDATE操作,会多。(大多数数据库默认级别是RC,比如SQL Server,Oracle),读取的时候不可以修改。
  • 可重复读: 同一个事务里确保每次读取的时候,获得的是同样的数据,但不保障原始数据被其他事务更新(幻读),Mysql InnoDB 就是这个级别。
  • 序列化:所有事物串行处理(牺牲了效率)
  • 《理解事务的4种隔离级别》
  • 数据库事务的四大特性及事务隔离级别
  • 《MySQL的InnoDB的幻读问题 》
    • 幻读的例子非常清楚。
    • 通过 SELECT … FOR UPDATE 解决。
  • 《一篇文章带你读懂MySQL和InnoDB》
    • 图解脏读、不可重复读、幻读问题。

MVCC

Java中的锁和同步类

公平锁 & 非公平锁

公平锁的作用就是严格按照线程启动的顺序来执行的,不允许其他线程插队执行的;而非公平锁是允许插队的。

悲观锁

悲观锁如果使用不当(锁的条数过多),会引起服务大面积等待。推荐优先使用乐观锁+重试。

乐观锁 & CAS

ABA 问题

由于高并发,在CAS下,更新后可能此A非彼A。通过版本号可以解决,类似于上文Mysql 中提到的的乐观锁。

CopyOnWrite容器

可以对CopyOnWrite容器进行并发的读,而不需要加锁。CopyOnWrite并发容器用于读多写少的并发场景。比如白名单,黑名单,商品类目的访问和更新场景,不适合需要数据强一致性的场景。

RingBuffer

可重入锁 & 不可重入锁

  • 《可重入锁和不可重入锁》
    • 通过简单代码举例说明可重入锁和不可重入锁。
    • 可重入锁指同一个线程可以再次获得之前已经获得的锁。
    • 可重入锁可以用户避免死锁。
    • Java中的可重入锁:synchronized 和 java.util.concurrent.locks.ReentrantLock
  • 《ReenTrantLock可重入锁(和synchronized的区别)总结》
    • synchronized 使用方便,编译器来加锁,是非公平锁。
    • ReenTrantLock 使用灵活,锁的公平性可以定制。
    • 相同加锁场景下,推荐使用 synchronized。

互斥锁 & 共享锁

互斥锁:同时只能有一个线程获得锁。比如,ReentrantLock 是互斥锁,ReadWriteLock 中的写锁是互斥锁。 共享锁:可以有多个线程同时或的锁。比如,Semaphore、CountDownLatch 是共享锁,ReadWriteLock 中的读锁是共享锁。

死锁