JAVA线程锁

锁的概念

锁就是线程用来对一代码块是否可以执行的条件,简单来说,如果某个线程想要执行一个同步代码块,那么如果他获得了该线程的锁,才可以执行;如果没有,则必须等待其他线程执行完该代码块释放锁,再次申请获得锁才可以执行。

把锁可以比喻成厕所上的锁,而线程就是需要上厕所的人,当一个人需要上厕所时,他会把厕所门用锁锁上,等到他使用完厕所,打开门,把锁交给另一个人,另一个人才可以继续上厕所

一、公平锁

公平锁是指线程按照申请锁的顺序来获取锁,先来后到

二、非公平锁

是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程先获得锁

公平锁和非公平锁可以用ReentrantLock实现

    public static void main(String[] args){
        ReentrantLock reentrantLock = new ReentrantLock(false)
    }

false代表非公平,true代表公平

区别:

公平锁/非公平锁

并发包中 ReentrantLock 的创建可以指定构造函数的 boolean 类型来得到公平锁或非公平锁,默认是非公平锁

关于两者区别:
公平锁:
公平锁,就是很公平,在并发环境中,每个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程是等 待队列的第一个,就占有锁,西则就会加入到等待队列中,以后会按照 FIFO 的规则从队列中取到自己

非公平锁
非公平锁比较粗鲁,上来就直接尝试占有锁,如果尝试失败,就再采用类似公平锁那种方式

sycronized就是非公平锁

三、可重入锁

指的是同一线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,在进入内层方法会自动获取锁。

scronized就是一个可重入锁是 也即是说,线程可以进入任何一个它已经拥有的锁所同步着的代码块。

public class HomeWork {
    public synchronized void way1(){
        System.out.println("第一个方法");
        way2();
    }
    public synchronized static void way2(){
        System.out.println("第二个方法");
    }
}

如图,第一个函数调用第二个函数,两个函数都用synchronized修饰,也就意味着,当某一个线程获得way1的锁时,同时也获得了way2的锁。

四、自旋锁


自旋锁( spinlock )
是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗 CPU。            

CAS就是一个自旋锁
 

五、独占锁和共享锁


独占锁: 指该锁一次只能被一个线程所持有、 对 ReentrantLock 和 Synchronized 而言都是独占锁
共享锁:指该锁可被多个线程所持有。
对 ReentrantReadWriteLock 其读锁是共享锁,其写锁是独占锁。
读锁的共享锁可保证并发读是非常高效的,读写,写读,写写的过程是互斥的
 

简单来说,读锁由于时共享锁,也就意味着可以多个线程同时读一份文件,提高效率;写锁作为独占锁,保证某个线程写某份文件时只能有该线程一个线程进行写操作,保证数据的一致性。


 

上一篇:一个简单的JAVA服务器-客户端模型


下一篇:AQS源码理解——ReentrantLock