【JAVA SE基础篇】62.多线程相关2
1.ThreadLocal(线程本地环境)
在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好。
因为局部变量只有线程自己能看见,不会影响其他线程。
ThreadLocal能够放一个线程级别的变量,其本身能够被多各线程共享使用,并且又能够达到线程安全的目的。
ThreadLocal就是想在多线程环境下去保证成员变量的安全。
常用方法:get/set/initialValue方法
JDK建议ThreadLocal定义为private static
ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程所有的调用到的方法都可以非常方便的访问这些资源。
Hibernate的Seesion工具类HibernateUtil
通过不同的线程对象设置Bean属性,保证各个线程Bean对象的独立性
例:
2.可重入锁
锁作为并发共享数据保证一致性的工具,大多数内置锁都是可重入的,也就是说,如果某个线程试图获取一个已经由它自己持有的锁时,
那么这个请求会立刻成功,并且会将这个锁的计数值+1.而当线程退出同步代码块时,计数器将会递减,当计数器等于0时,锁释放。
如果没有可重入锁的支持,在第二次企图获得锁时会进入死锁状态。
例:
3.CAS
锁分为两类:
悲观锁:synchronized是独占锁即悲观锁,会导致其他所有需要锁的线程挂起,等待持有锁的线程释放锁。
乐观锁:每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止
Compare and Swap(CAS) 乐观锁的实现:
有三个值:当前内存值V,旧的预期值A,将更新的值B。
先获取V的值,再用V和A作比较,如果相等就修改为要B,并返回true,否则什么都不做返回false
注:CAS是原子操作,不会被外部打断,属于硬件级别操作,效率比锁高
纯在问题:
ABA问题:如果V初次读取时是A,并在准备赋值的时候检查到它仍然是A,那能说明它的值仍然是A
不能说明他的值没有被其他线程修改。如果曾经被改成B,又改回A,那么CAS就会误认为没有被修改
例: