【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就会误认为没有被修改

例:

原文地址:https://www.cnblogs.com/chengkuan/p/13385480.html