Java中的线程安全

什么是线程安全

线程安全指在多线程环境下,共享资源能够被多个线程安全地访问和修改,不会出现数据异常或不一致的情况。

Threadlocal

每个线程在访问该变量时,都会拷贝一个副本至本地内存,所以多线程下操作ThreadLocal变量时,各自都是在操作自己拷贝的副本,互不影响,这样自然而然就避免了线程安全问题。

Threadlocal包含一个静态内部类ThreadLocalMap。
Map里面存储线程本地对象ThreadLocal(key)和线程的变量副本(value)。

Threadlocal应用

在Spring项目中Dao层中装配的Connection肯定是线程安全的,其解决方案就是采用ThreadLocal方法,当每个请求线程使用Connection的时候, 都会从ThreadLocal获取一次,如果为null,说明没有进行过数据库连接,连接后存入ThreadLocal中,如此一来,每一个请求线程都保存有一份 自己的Connection。于是便解决了线程安全问题

Threadlocal内存溢出

线程的threadLocals放入的entry没有被及时的remove掉

volatile关键字

volatile变量每次被线程访问时,都强迫线程从主内存中重读该变量的最新值

synchronized(自动释放锁)

通过使用synchronized关键字来确保在同一时刻只有一个线程能够访问共享资源。可以应用于方法级别或代码块级别。

// 同步方法
public synchronized void synchronizedMethod() {
    // 共享资源访问
}

// 同步块
public void synchronizedBlock() {
    synchronized (lockObject) {
        // 共享资源访问
    }
}

synchronized关键字用在方法和代码块上的区别

同步方法直接在方法上加synchronized实现加锁,同步代码块则在方法内部加锁,很明显,同步方法锁的范围比较大,而同步代码块范围要小点,一般同步的范围越大,性能就越差

Lock(finally块中写unlock()手动释放锁)

lock是一个接口,手动在finally块中写unlock()以防死锁。

ReadWriteLock

Synchronized依赖JVM而Reentrantlock API

ReentrantLock

以ReentrantLock为例,state初始化为0,表示未锁定状态。A线程lock()时,会调用tryAcquire()独占该锁并将state+1。此后,其他线程在tryAcquire()时就会失败,直到A线程unlock()到state=0(即释放锁)为止,其它线程才有机会获取该锁。当然,释放锁之前,A线程自己是可以重复获取此锁的(state会累加),这就是可重入的概念。但要注意,获取多少次就要释放多少次,这样才能保证state是能回到零态的。

CountDownLatch

CountDownLatch 定义了一个计数器,和一个阻塞队列,计数器递减到0时会唤醒阻塞队列所有线程

可重入锁和不可重入锁

ReentrantLock和synchronized都是可重入锁

公平锁与非公平锁

JVM 随机就近原则分配锁的机制则称为不公平锁,非公平锁实际执行的效率要远超公平锁,除非程序有特殊需要,否则最常用非公平锁的分配机制。
非公平锁性能比公平锁高 5~10 倍,因为公平锁需要在多核的情况下维护等待队列
-Java 中的 synchronized 是非公平锁,ReentrantLock 默认的 lock()方法采用的是非公平锁(构造时提供了公平);

公平锁指的是锁的分配机制是公平的,通常先对锁提出获取请求的线程会先被分配到锁

锁升级

偏向锁

偏向锁,顾名思义,它会偏向于第一个访问锁的线程
将锁对象的状态标志位改为01,即偏向模式。然后使用CAS操作将线程的ID记录在锁对象的Mark Word中。以后该线程可以直接进入同步块,连CAS操作都不需要

轻量级锁(自旋锁)

轻量级锁采用CAS自旋锁的方式来完成加锁,轻量级锁膨胀为重量级锁的条件就是自旋达超过一定次数(默认为10

重量级锁

当后续线程尝试获取锁时,发现被占用的锁是重量级锁,则直接将自己挂起,等待将来被唤醒。在JDK1.6之前,synchronized直接加重量级锁,很明显现在得到了很好的优化。
重量级锁的特点:会让抢占锁的线程从用户态转变为内核态,其他线程试图获取锁时,都会被阻塞,只有持有锁的线程释放锁之后才会唤醒这些线程。

AQS(AbstractQuenedSynchronizer)抽象队列同步器

  1. state 状态
  2. CLH(Craig,Landin,and Hagersten)队列是一个虚拟的双向队列
  3. 获取/释放

原文链接:https://blog.csdn.net/qq_40722827/article/details/105598682

待更新、、

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值