一、概述
在编程中,很多人都会尝试使用多线程的方式去编程,但是却很难保证自己写出来的多线程程序的正确性,在多线程中如果涉及到对共享资源的并发读写,这时就会产生资源的争夺。而在资源争夺中,第一想到的就是使用锁 ,对共享资源进行数据保护。
二、种类及区别
公平锁/非公平锁
这个是在ReentrankLock中实现的,synchronized没有,是用一个队列实现的,在公平锁好理解,就是先进这个队列的,也先出队列获得资源,而非公平锁的话,则是还没有进队列之前可以与队列中的线程竞争尝试获得锁,如果获取失败,则进队列,此时也是要乖乖等前面出队才行
可重入锁
如果一个线程获得过该锁,可以再次获得,主要是用途就是在递归方面,还有就是防止死锁,比如在一个同步方法块中调用了另一个相同锁对象的同步方法块
独享锁/共享锁
共享锁可以由多个线程获取使用,而独享锁只能由一个线程获取。
对ReentrantReadWriteLock其读锁是共享锁,其写锁是独占锁
读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的。其中获得写锁的线程还能同时获得读锁,然后通过释放写锁来降级。读锁则不能升级
互斥锁/读写锁
上面讲的独享锁/共享锁就是一种广义的说法,互斥锁/读写锁就是具体的实现。
互斥锁在Java中的具体实现就是ReentrantLock
读写锁在Java中的具体实现就是ReadWriteLock
乐观锁/悲观锁
乐观锁就是乐观的认为不会发生冲突,用cas和版本号实现
悲观锁就是认为一定会发生冲突,对操作上锁
分段锁
在1.7的concurrenthashmap中有分段锁的实现,具体为默认16个的segement数组,其中segement继承自reentranklock,每个线程过来获取一个锁,然后操作这个锁下连着的map。
偏向锁/轻量级锁/重量级锁
在jdk1.6中做了第synchronized的优化,
偏向锁指的是当前只有这个线程获得,没有发生争抢,此时将方法头的markword设置成0,然后每次过来都cas一下就好,不用重复的获取锁
轻量级锁:在偏向锁的基础上,有线程来争抢,此时膨胀为轻量级锁,多个线程获取锁时用cas自旋获取,而不是阻塞状态
重量级锁:轻量级锁自旋一定次数后,膨胀为重量级锁,其他线程阻塞,当获取锁线程释放锁后唤醒其他线程。(线程阻塞和唤醒比上下文切换的时间影响大的多,涉及到用户态和内核态的切换)
自旋锁:在没有获取锁的时候,不挂起而是不断轮询锁的状态
网友评论