Java中的锁和原子类

可重入锁

可重入锁,也叫做递归锁,指的是在同一线程内,外层函数获得锁之后,内层递归函数仍然可以获取到该锁。换一种说法:同一个线程再次进入同步代码时,可以使用自己已获取到的锁。
主要作用是避免思索以及节省获取锁的时间。
Synchronized 和 ReentrantLock都是可重入锁。

public class SynchronizedTest {
    public static void main(String[] args) {
        SynchronizedTest synchronizedTest = new SynchronizedTest();
        synchronizedTest.tell();
    }

    public synchronized void tell() {
        System.out.println("进入tell");
        tell2();
    }

    public synchronized void tell2() {
        System.out.println("进入tell2");
    }
}
//结果是
//进入tell
//进入tell2

读写锁

适用于程序中写操作没有读操作那么频繁。在没有写操作的时候,两个线程同时读一个资源没有任何问题,所以应该允许多个线程能在同时读取共享资源。但是如果有一个线程想去写这些共享资源,就不应该再有其它线程对该资源进行读或写例如:(读-读能共存,读-写不能共存,写-写不能共存)
java5在java.util.concurrent包中提供了读写锁的实现,ReentrantReadWriteLock

悲观锁

悲观的认为每次取数据时都认为其他线程会修改,所以都会加锁,当其他线程想要访问数据时,都需要阻塞挂起。Java中synchronized的思想也是悲观锁。

乐观锁

乐观的认为不会发生并发操作,所以本质是没有锁,所以会效率比较高,无阻塞。
他的实现是在更新数据的时候判断有没有对数据及进行修改。一般会使用version机制实现。
version方式
一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当修改的时候查看version是否改变,如果没改变则修改成功,否则重试修改,直到更新成功。

select version from table where x=y;
update table set x=x+1, version=version+1 where id=#{id} and version=#{version};  

CAS无锁(Compare And Swap)

与锁相比,使用比较交换(下文简称CAS)会使程序看起来更加复杂一些。但由于其非阻塞性,它对死锁问题天生免疫,并且,线程间的相互影响也远远比基于锁的方式要小。更为重要的是,使用无锁的方式完全没有锁竞争带来的系统开销,也没有线程间频繁调度带来的开销,因此,它要比基于锁的方式拥有更优越的性能。
java5后的并发包提供了几个CAS实现的原子类

  • AtomicBoolean
  • AtomicInteger
  • AtomicLong
  • AtomicReference

小Tip:在java早期版本中,Synchronized是重量级锁,因为底层依赖操作系统的Mutex Lock的,java的线程池是映射到系统中的原生线程上的,如果要挂起或者唤醒一个线程,都需要操作系统帮助完成,操作系统完成线程的去切换需要从用户态转换为内核态,事件成本较高,这也是为什么java6之前Synchronized效率低下的原因。
从java6之后,官方对sychronized引入了大量优化,包括偏量锁,轻量级锁、自旋锁,适应性自旋锁、锁消除、锁粗化等技术,用于减少锁的开销。
锁主要有4个状态,一次是无锁、轻量级锁、自旋锁、重量级锁。它们会随着竞争激烈而逐渐升级,且只可升级,不可降级。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值