什么是锁?有几种锁?怎么用锁?

生活中,我们在门上可以见到锁,在手机上可以见到锁,在电脑上,汽车上,保险柜上......等等,可见锁在我们生活中是一个随处可件的物品,但我们今天要讲的是,java中的锁。本篇文章仅博主个人观点,仅供参考,共同进步,感谢博友支持。

什么是锁?

将某种资源私有化的一种物品,没错java里面的锁也是这种特性,它可以让某个方法,某个变量或某个通道,在某个时刻下只能被一个线程占用。只有当这个锁释放了,另外的线程才可以使用。例子:上厕所,一个同事上厕所把门锁上,这个时候厕所就被上锁了,别人要想进去,只能等这位同事释放锁后出来,其他同事才可进入。这个厕所可以看成是临界区,同事就是线程。

临界区?

多个线程共享同一个资源的情况,为了防止出现数据不一致情况的发生,人们引入了临界区的概念。临界区是一个用来访问共享资源的代码块,同一时间内只运行一个线程进入。

有几种锁?

java体系中有几种锁呢?

  • synchronized(不公平)
  • ReentrantLock 重入锁 (可公平可不公平)
  • ReadWriteLock 读写锁(不公平)

公平?不公平

公平锁会按照时间的先后顺序来给予锁

不公平锁在等待队列随机挑选一个来给予锁

例子:银行办理业务排队,一堆人要办业务,都围在窗口前,业务员也顾不得前后,顺便就找个人办理,这样是不公平的,而公平的则是先到先办理后到后办理

怎么用锁?

要想知道怎么用锁需要清楚每个锁的特点,才能对症下药。

例子:在不带锁的情况下,线程同时进入方法,如果业务处理的是减库存又或者是加减金额,就会出现由高并发下带来的问题,导致数据错误混乱

public class SynchronizedDemo {

    public static void addAmount() {
        System.out.println("进入方法");
        try {
            // 模拟业务处理
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("退出方法");
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(() -> addAmount()).start();
        }
    }
}
结果:
进入方法
进入方法
进入方法
退出方法
退出方法
退出方法

synchronized

特性:可重入,可见性

缺点:效率比较低,不够灵活,不可中断,无法感知获取锁

package com.zqh.www;

public class SynchronizedDemo {

    public synchronized static void addAmount() {
        System.out.println("进入方法");
        try {
            // 模拟业务处理
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("退出方法");
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(() -> addAmount()).start();
        }
    }
}
进入方法
退出方法
进入方法
退出方法
进入方法
退出方法

ReentrantLock:synchronized的增强版

特性:效率较高,灵活,可感知获取锁,可公平可非公平,可中断

缺点:需在finally释放锁

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockDemo {

    private static ReentrantLock reentrantLock = new ReentrantLock();

    public static void addAmount() {
        reentrantLock.lock();
        try {
            System.out.println("进入方法");
            try {
                // 模拟业务处理
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("退出方法");
        } finally {
            reentrantLock.unlock();
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(() -> addAmount()).start();
        }
    }
}
进入方法
退出方法
进入方法
退出方法
进入方法
退出方法

ReadWriteLock

特性:效率较高,灵活,可感知获取锁,读写分离控制(读多写少),读读并行,读写串行,写写串行

缺点:需在finally释放锁

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockDemo {
    private static ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    private static Lock readLock = reentrantReadWriteLock.readLock();
    private static Lock writeLock = reentrantReadWriteLock.writeLock();
    private static volatile int value = 0;

    public static void readAmount() {
        readLock.lock();
        try {
            System.out.println("查看金额:" + value);
            try {
                // 模拟业务处理
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } finally {
            readLock.unlock();
        }
    }

    public static void addAmount() {
        writeLock.lock();
        try {
            System.out.println("进入方法");
            try {
                // 模拟业务处理
                ++value;
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("退出方法");
        } finally {
            writeLock.unlock();
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(() -> readAmount()).start();
        }
        for (int i = 0; i < 3; i++) {
            new Thread(() -> addAmount()).start();
        }
    }
}

 

  • 21
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值