Java Lock锁使用场景

叙述

提到锁,就会想到数据库锁、Java内置锁、分布式锁

使用场景

首先,需要加锁的资源一定是临界资源,所谓临界资源就是在多线程的情况下,各个线程会进行抢占的资源。下面以一段代码来说明:

public class LockDemo {
    
    

    private static int count = 500;

    public static void main(String[] args) throws Exception {
    
    

        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 500; i++){
    
    
            threadPool.submit(() -> {
    
    
                count--;
            });
        }
        threadPool.shutdown();
        Thread.sleep(5000);
        System.out.println(count);
    }
}

结果:2

然后创建了500个任务,把这五百个任务丢到线程池里去处理,每个任务会对count进行减一。

理想情况下,count应该为0,但实际count最后为2。

其原因就是因为在多线程环境下,各个线程对count发生了资源的争夺,导致了数据的不安全性。

其中,count就是临界资源,多线程就是我们常说的并发环境。

加完Lock锁后的代码

public class LockDemo {
    
    

    private static int count = 500;

    public static void main(String[] args) throws Exception {
    
    
        Lock lock = new ReentrantLock();

        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 500; i++){
    
    
            threadPool.submit(() -> {
    
    
                lock.lock();
                count--;
                lock.unlock();

            });
        }
        threadPool.shutdown();
        Thread.sleep(5000);
        System.out.println(count);
    }
}

代码整体没有太大变化,只是在count–前后做了加锁和减锁操作,最后无论代码运行多少次,结果都是0(需要注意的是这里忽略了可见性),没有出现未加锁时的少减情况。

这就是锁的使用场景,无论是数据库锁、java内置锁还是分布式锁,他们的使用场景都大同小异。

使用锁的目的就是为了控制临界资源的安全性。

如果使用了tryLock(),他会在判断在使用锁的情况下,默认跳过count–操作,最终结果是51。

如果不使用tryLock(),默认是等待解锁后继续往下执行。

Lock详解

使用如下代码创建Lock锁,Lock是一个接口,而是实现ReentrantLock

// 默认非公平锁
Lock lock = new ReentrantLock();

// 公平锁
Lock lock = new ReentrantLock(true);

源码如下:

public ReentrantLock() {
    
    
	sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
    
    
    sync = fair ? new FairSync() : new NonfairSync();
}

Lock属性

void lock()获得锁
void lockInterruptibly()获取锁定,除非当前线程是 interrupted 。
Condition newCondition()返回一个新Condition绑定到该实例Lock实例。
boolean tryLock()只有在调用时才可以获得锁。
boolean tryLock(long time, TimeUnit unit)如果在给定的等待时间内是空闲的,并且当前的线程尚未得到 interrupted则获取该锁。
void unlock();释放锁

文章参考:
https://blog.csdn.net/m0_50370837/article/details/124471888
https://blog.csdn.net/qq_42871327/article/details/115970315

https://mp.weixin.qq.com/s?__biz=MzU1MjMzNzUwNg==&mid=2247484229&idx=1&sn=9a67add64bf3c9fee15faf63c6df5c38&chksm=fb82ea48ccf5635ea0edc5ff40662680102d6e9e04ce30686332abd860e940f250b7cae0161c&scene=27

猜你喜欢

转载自blog.csdn.net/u014641168/article/details/129932494
今日推荐