并发编程

java里面的各种锁总有你不知道的

2020-04-28  本文已影响0人  java金融

什么是锁

在计算机科学中,锁(lock)或互斥(mutex)是一种同步机制,用于在有许多执行线程的环境中强制对资源的访问限制。锁旨在强制实施互斥排他、并发控制策略。
锁通常需要硬件支持才能有效实施。这种支持通常采取一个或多个原子指令的形式,如"test-and-set", "fetch-and-add" or "compare-and-swap"”。这些指令允许单个进程测试锁是否空闲,如果空闲,则通过单个原子操作获取锁。

公平锁

 /**
     *     true 表示 ReentrantLock 的公平锁
     */
    private ReentrantLock lock = new ReentrantLock(true);

    public   void testFail(){
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() +"获得了锁");
        }finally {
            lock.unlock();
        }
    }
    public static void main(String[] args) {
        FairLockTest fairLock = new FairLockTest();
        Runnable runnable = () -> {
           System.out.println(Thread.currentThread().getName()+"启动");
            fairLock.testFail();
        };
        Thread[] threadArray = new Thread[10];
        for (int i=0; i<10; i++) {
            threadArray[i] = new Thread(runnable);
        }
        for (int i=0; i<10; i++) {
            threadArray[i].start();
        }
    }

运行结果

Thread-1启动
Thread-1获得了锁
Thread-3启动
Thread-3获得了锁
Thread-5启动
Thread-5获得了锁
Thread-2启动
Thread-2获得了锁
Thread-4启动
Thread-4获得了锁
Thread-6启动
Thread-6获得了锁
Thread-10启动
Thread-8启动
Thread-10获得了锁
Thread-9启动
Thread-7启动
Thread-8获得了锁
Thread-9获得了锁
Thread-7获得了锁

看到结果里面获得锁的顺序和线程启动顺序是一致的,这就是公平锁。

非公平锁

Thread-1启动
Thread-0启动
Thread-2启动
Thread-3启动
Thread-4启动
Thread-8启动
Thread-7启动
Thread-6启动
Thread-1获得了锁
Thread-0获得了锁
Thread-5启动
Thread-5获得了锁
Thread-2获得了锁
Thread-3获得了锁
Thread-4获得了锁
Thread-8获得了锁
Thread-7获得了锁
Thread-6获得了锁
Thread-9启动
Thread-9获得了锁

线程启动顺序是1、0、2、3、 4、 8 、7 、6 、5 、9,获得锁的顺序却是1 、0 、5 、2 、3 、4 、8 、7 、6 、9,这就是非公平锁,它不保证先排队尝试去获取锁的线程一定能先拿到锁。

重入锁

public class ReentrantLockTest {


    public static void main(String[] args){
        for (int i = 0; i < 10; i++) {
           new Thread(() -> A()).start();
        }
    }
    public static   synchronized void  A(){
        System.out.println(Thread.currentThread().getName());
        B();
    }
    public static synchronized void  B(){
        System.out.println(Thread.currentThread().getName());
    }
}

输出:

Thread-1
Thread-1
Thread-0
Thread-0

A方法和B方法同时输出了线程名称,表明即使递归使用synchronized也没有发生死锁,证明其是可重入的。

读写锁

百度百科定义的读写锁是:

读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。

乐观锁、悲观锁

分段锁

分段锁其实是一种锁的设计,并不是具体的一种锁,对jdk1.7 及以前的ConcurrentHashMap而言,其并发的实现就是通过分段锁的形式来实现高效的并发操作。分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。

自旋锁

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

偏向锁、轻量级锁、重量级锁

这三种锁是指锁的状态,并且是针对Synchronized。在Java 5通过引入锁升级的机制来实现高效Synchronized。这三种锁的状态是通过对象监视器在对象头中的字段来表明的。

独享锁、共享锁

参考文章
https://blog.csdn.net/qiuwenjie123/article/details/79950532
https://segmentfault.com/q/1010000009659039
https://blog.csdn.net/qq_43519310/article/details/100107346
https://blog.csdn.net/u010648018/article/details/79750608
https://www.cnblogs.com/hustzzl/p/9343797.html
http://ifeve.com/locks/

上一篇 下一篇

猜你喜欢

热点阅读