数据库-事务
安全隐患
读:
脏读 (一个事务读到了另一个事务未提交的数据)
不可重复读(一个事务读到了另一个事务已经提交的数据,造成前后两次查询不一致)
幻读(一个事务读到了另一个事务insert的数据)
写:
丢失更新(两者首先读到同样的数据,但是后面更改的数据覆盖了前面的更改)

解决方法
1.悲观锁
依靠数据库的锁机制实现
select * from account for update;(数据库锁机制,排他锁)
例如:行锁,表锁,读锁,写锁等,都是在操作之前就上锁。Java中synchronized和reentrantLock等独占锁也是悲观锁思想的体现。
缺点:数据库性能的大量开销(特别对于长事务)
2.乐观锁
方法:版本号机制、CAS算法
版本号机制:在数据表中加上version字段,表示数据被修改的次数,修改一次,加1.当事务A更改数据时,当开始读取到的版本号与数据库当前版本号相同时才更新,否则重新更新。
CAS算法(非阻塞同步):
需要读写的内存值V 进行比较的值A 拟写入的新值B
场景:适用于多读的应用类型,如数据库的write_condition机制,java中java.util.concurrent.atomic包下的原子变量类(CAS)
缺点:ABA问题
隔离级别
读未提交: 脏读
读已提交: 不可重复读
可重复读 : 解决脏读,不可重复读,不能解决幻读(mysql默认)
可串行化:解决以上
JUC
volatile关键字
内存可见性问题:当多个线程操作共享数据时,彼此不可见。
作用:当多个线程操作共享数据时,可以保证内存中的数据可见。
相较于synchronized是一种较为轻量级的同步策略
区别
1.volatile 不具备互斥性 多个线程都可以访问共享数据(数据在主存中)
2.volatile 不能保证变量的原子性
在什么情况下volatile能够保证线程安全 ?
1.运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值。
2.变量不需要与其他状态变量共同参与不变约束。????????????
应用场景:单例模式
原子性:
原子变量 java.util.concurrent.atomic包下提供了常用的原子变量
1.volatile修饰,保证了内存可见性
2.CAS算法保证了数据的原子性
cas算法是硬件对于并发操作共享数据的支持
CAS:
1.操作数:内存值V 预估值A 更新值B :只有V==A时,V=B,否则不做任何操作。

2.比同步锁的效率高很多,因为一次尝试失败后,不会放弃cpu资源,而是继续尝试。
3.缺点:手写代码较多。
4.使用方法:
private AtomicInteger s=new AtomicInteger();
s.compareAndSet();
concurrentHashMap
锁分段机制(并行+效率高)
是一个线程安全的哈希表,采用锁分段代替hashtable的独占锁,提高性能。
concurrentLevel:分段级别(默认16)

jdk1.8以后?????????????????
当期望许多线程访问一个给定的collection时:
concuerrenthashmap 优于 hashmap
concurrentskiplistmap 优于 treemap
copyonWriteArraylist (写入并复制) 优于 arraylist
CountDownLatch闭锁
在完成某些运算时,只有其他所有线程的运算全部完成,当前运算才会继续执行。
对线程进行控制,例如,对多个线程任务进行计时。
latch.countDown();每运行完1,减1;
latch.await(); 等到所有线程运算结束,再进行总运算,如电商中不同种类商品销量总统计。
创建多线程的方式3:
实现callable接口(可以有返回值,并可以抛出异常)
class threadDemo implements Callable<Integer>{
public Integer call() throws Exception{
}
}
执行callable,需要futureTask实现类支持。
lock同步锁
解决多线程安全的方法:同步代码块,同步方法,同步锁 lock(显式锁)
方法:通过lock()方法上锁,再通过unlock方法进行释放锁(放在finally)。
等待唤醒机制
生产消费者案例
线程池
作用:提供了一个线程,队列中保存着所有等待状态的线程,避免了创建与销毁的额外开销,提供响应速度。
体系结构:
java.util.concurrent.Executor 负责线程的使用与调度的根接口
ExecutorService 子接口:线程池的主要接口
ThreadPoolExecutor 线程池的实现类
ScheduledExecutorService 子接口:负责线程的调度的子接口
ScheduledThreadPoolExecutor 实现类:继承ThreadPoolExecutor ,实现ScheduledExecutorService
forkJoinPool分支合并框架
大任务分解为小任务,再将结果进行合并。
工作窃取模式:
java线程的状态

sleep和wait的区别
1.sleep方法正在执行的线程主动让出CPU资源,在sleep指定时间后cou再回到该线程下继续往下执行,但是并不会释放同步资源锁;
而wait方法是当前线程让自己暂时退出出同步资源锁,只有调用了notify方法,才能让调用了wait方法的线程去参与竞争同步资源锁。
2.sleep方法可以在任何地方使用,而wait方法只能在同步方法或者同步块中使用。
3.sleep是线程类Thread的方法,到时间自动恢复;而wait是object方法,放弃对象锁,进入等待队列。

浙公网安备 33010602011771号