• (锁) 系列篇 --“一、锁的基本概念”


     

    (锁) 系列篇

    锁的概念,更多源于生活。每家每户都有一把锁,只有持有钥匙打开锁才能进入房屋,以此来防止盗贼进入家中。

    1、为什么需要锁?

    引申到软件世界高并发场景,锁即为竞争资源。只有拿到锁才能访问资源,否则进入锁等待区,以此保护资源顺序性访问防止乱序访问。

    2、Java对象锁

    Java每个对象都是Object的子类有且只有一个锁,言外之意每个对象都可作为互斥资源来实现有序访问。以32位JVM对象头为例,根据锁状态(后续补充)具有不同标志位

     (图片来自《Java并发编程的艺术》)

    对象锁有两个等待池:

    • Entry Set池:等待获锁池,当锁被释放之后有机会竞争获锁;
    • Wait Set池:等待挂起池,调用wait之后进入该池,不能直接竞争获锁。只有当锁对象调用notify、notifyAll 唤醒后进入Entry Set池,才可竞争获锁;

    /**
     * Class {@code Object} is the root of the class hierarchy.
     * Every class has {@code Object} as a superclass. All objects,
     * including arrays, implement the methods of this class.
     *
     * @author  unascribed
     * @see     java.lang.Class
     * @since   JDK1.0
     */
    public class Object {
        //........
         
        // 锁基本操作方法:获取锁、释放锁
        public final native void notify();
        public final native void notifyAll();
        public final native void wait(long timeout) throws InterruptedException;
        public final void wait(long timeout, int nanos) throws InterruptedException {
            if (timeout < 0) {
                throw new IllegalArgumentException("timeout value is negative");
            }
    
            if (nanos < 0 || nanos > 999999) {
                throw new IllegalArgumentException(
                                    "nanosecond timeout value out of range");
            }
    
            if (nanos > 0) {
                timeout++;
            }
    
            wait(timeout);
        }
        public final void wait() throws InterruptedException {
            wait(0);
        }
    }

    经常会被问到wait、notify方法为什么不放在Thread类里面,而是在Object类中?

    实质是wait、notify都属于锁本身操作而非线程操作。每个对象都有且只有一个锁,定义在Object类中每个子类都将继承这些基本的操作,实现代码复用。

    3、分布式锁

    前面引申的锁概念都发生进程内,而在分布式环境的资源竞争就起不到作用。例如秒杀服务大多都是分布式部署,库存为100而参与秒杀用户为1w,如何保证不超卖和少卖呢?

    此时需要用到分布式锁将资源状态外置,保证资源一致性。比如常用Mysql行锁或者表锁进行控制,将锁的实现细节丢给数据库,保证库存更新的顺序性。

    然而锁往往会成为数据库负担,可引入redis、zookeeper分布式锁缓解数据库压力。需要注意的是大并发场景其实不适合使用锁,这里只是做个引申示例。

  • 相关阅读:
    10 Iterable之遍历Map、Set、Array
    9 Map和Set
    8 循环
    5 字符串
    6 数组
    4 数据类型
    2 变量
    实现简单的邮件收发器(十二)
    10.19 初识django
    10.18 数据库之索引优化方案
  • 原文地址:https://www.cnblogs.com/xiaoxing/p/12550836.html
Copyright © 2020-2023  润新知