java线程安全 - 加锁机制

本文详细介绍了多线程编程中的线程安全概念及多种锁机制,包括synchronized、ReentrantLock、Semaphore等,探讨了它们的工作原理及应用场景。

多线程是我们在编程中必然会遇到的、非常基础、非常重要的知识。我们在编程时,头脑中,必须要有多线程的意识(高并发的意识)。虽然很基础,但是也有其难度。这篇博客,将简单介绍面对多线程时,加锁的处理方式。

线程安全的定义

多个线程之间的操作,无论采用何种执行时序或交替方式,都要保证不变性条件不被破坏。

当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么这个类是线程安全的。

内置锁

java的内置锁,相当于一种互斥体(互斥锁)。性能较低。可重入。

同步代码块 - synchronized

  • 作为锁的对象引用

每个Java对象,都可以用做一个实现同步的锁。

之所以每个对象都有一个内置锁,只是为了免去显示地创建锁对象。

  • 作为由这个锁保护的代码块

  • 可重入

如果某个线程试图获取一个已经由它自己持有的锁,那么这个请求就会成功。

当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取计数值置为1。如果同一个线程再次获取这个锁,计数值将递增,而当线程退出同步代码块时,计数器会相应地递减。当计数值为0时,这个锁将被释放。

当执行时间较长的计算或者可能无法快速完成的操作(例如:网络IO或者控制台IO),一定不要持有锁!

1. Synchronized

互斥锁。

synchronized实现的机理依赖于软件层面上的JVM。

如果当前多线程的性能瓶颈在锁上,可以考虑更换其他机制的锁。

自旋锁 - 避免用户线程和内核的切换。,尽可能的减少阻塞的可能性。对于占用锁时间比较短的代码块来说性能能大幅度的提升!

偏向锁 - 主要用于解决无竞争下面锁的性能问题。

2. Lock

互斥锁。

纯Java实现。

ReentrantLock、ReadWriteLock(ReentrantReadWriteLock)、AbstractQueuedSynchronizer(是一个同步器,支持获取锁和释放锁两个操作)

高并发下,ReentrantLock的性能比Synchronized高很多。

lock()、unlock(),使用ReentrantLock必须在finally控制块中进行解锁操作。

可轮询锁 - 提供了tryLock()轮询方法来获得锁,如果锁可用则获取锁,如果锁不可用,则此方法返回false,并不会为了等待锁而阻塞线程,这极大地降低了死锁情况的发生。

定时锁 - 使用Lock.tryLock(long timeout, TimeUnit unit)来指定让线程在timeout单位时间内去争取锁资源,如果超过这个时间仍然不能获得锁,则放弃锁请求,定时锁可以避免线程陷入死锁的境地。

3. Semaphore

通过acquire()与release()方法来获得和释放临界资源。释放锁的操作也必须在finally代码块中完成。

提供了可轮询锁、定时锁、公平锁、非公平锁。

支持多个临界资源,而ReentrantLock只支持一个临界资源

4. AtomicInteger

AtomicReference

通常AtomicInteger的性能是ReentantLock的好几倍。

转载于:https://my.oschina.net/xiaowangqiongyou/blog/1863353

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值