锁的分类

本文深入探讨了Java内存模型的细节,包括线程独有的运行内存和共有的主存储概念,以及如何通过synchronized和volatile等关键字确保数据的正确性和一致性。同时,文章讨论了指令重排序的影响和锁的多种类型,如独占锁、分拆锁、分离锁和分布式锁,以及它们在并发编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 在共享内存的多处理器体系架构中,每个处理器都拥有自己的缓存,并且定期地与主内存进行协调。
  • 在不同的处理器架构中提供了不同级别的缓存一致性(Cache Coherence),
    • 其中一部分只提供最小的保证,即允许不同的处理器在任意时刻从同一个存储位置上看到不同的值。
  • 操作系统、编译器以及运行时(有时甚至包括应用程序)需要弥合这种在硬件能力与线程安全之间的差异。

java内存模型

  • 抽象出线程独有的运行内存和共有的主存储
  • 为了使java开发人员无须关心不同架构内存模型之间的差异,
  • Java还提供了自己的内存模型,并且JVM通过在适当的位置上插入内存栅栏(内存屏障)来屏蔽在JVM与底层之平台内存模型之间的差异。
  • 线程中的变量何时同步回到内存是不可预期的
    • java内存模型规定,通过关键词”synchronized“、”volatile“可以让java保证某些约束。
    • “volatile” - 保证读写的都是主内存变量。
    • “synchronized” - 保证在块开始时,都同步主内存值到工作内存,而快结束时,将工作内存同步会主内存。

指令重排序::

    public class PossibleReordering {
        static int x = 0, y = 0;
        static int a = 0, b = 0;

        public static void main(String[] args) throws InterruptedException {
            Thread one = new Thread(new Runnable() {

                @Override
                public void run() {
                    a = 1;
                    x = b;
                }
            });

            Thread two = new Thread(new Runnable() {

                @Override
                public void run() {
                    b = 2;
                    y = a;
                }
            });
            one.start();
            two.start();
            one.join();
            two.join();
            System.out.println("x:" + x + ",y:" + y);
        }
    }
  • 执行结果,一般人可能认为是1,1;真正的执行结果可能每次都不一样。
  • 拜JMM重排序所赐,JMM使得不同线程的操作顺序是不同的,
  • 从而导致在缺乏同步的情况下,要推断操作的执行结果将变得更加复杂。
  • 同步将限制编译器和硬件运行时对内存操作重排序的方式。

锁synchronized

  • 锁实现了对临界资源的互斥访问,是严格的排它锁、互斥锁。
  • JVM规范通过两个内存屏障(memory barrier)命令来实现排它逻辑。
    • 内存屏障可以理解成顺序执行的一组CPU指令,完全无视指令重排序。
  • 类锁(锁是TestSTatic.class对象)、对象锁

独占锁

  • 如果你不敢确定该用什么锁,就用这个吧,在保证正确的前提下,后续在提高开发效率。

分拆锁

  • 如果将这些锁请求分到更多的锁上,就能有效降低锁竞争程度。
  • 由于等待而被阻塞的线程将更少,从而可伸缩性将提高。
  • 同时使用俩

分离锁

  • 在某些情况下,可以将锁分解技术进一步扩展为对一组独立对象上的锁进行分解,这种情况称为锁分段
  • 例如ConcurrencyHashMap是有一个包含16个锁的数组实现
  • 锁分段的劣势在于:
    • 与采用单个锁来实现独占访问相比,
    • 要获取多个锁来实现独占访问将更加困难并且开销更高,
    • 比如计算size、重hash。

分布式锁

  • zookeeper,判断临时节点是否存在,存在就说明已经有人争抢到锁;
  • 不存在就创建节点,表明拥有该锁。

volatile

  • volatile是比synchronized更轻量级的同步原语,
  • volatile可以修饰实例变量、静态变量、以及数组变量(引用)。
  • 被volatile修饰的变量,JVM规范规定,一个线程在修改完,另外的线程能读取最新的值。
  • 仅仅保证可见性,不保证原子性
<think>好的,用户想了解IT上下文中的分类和类型。首先,我需要回忆的基本概念和在计算机科学中的应用。主要用于并发控制,确保资源在多线程或分布式环境中的正确访问。 根据之前的引用,比如引用[1]提到加成功时生成锁结构,is_waiting属性为false,说明可能有不同的状态,比如等待或持有。这可能涉及到的排他性和共享性,所以首先应该区分排他和共享。排他(X)用于写操作,防止其他事务同时修改;共享(S)允许读操作共享资源。 接下来,引用[3]提到服务器配置中的不同类型,可能涉及数据库和编程语言中的。比如,数据库中的可以分为行级、表级等粒度不同的类型。编程语言中的,如互斥、读写,这些属于实现层面的。 然后,分布式系统中的,比如Redis实现的分布式,需要考虑CAP理论下的实现方式,如基于ZooKeeper或Redis。这里需要提到分布式的特点和应用场景。 另外,死的问题也是分类中的一个方面,比如预防死的方法,如顺序加、超时机制等。乐观和悲观是两种不同的并发控制策略,乐观假设冲突少,通过版本号控制;悲观则先加再访问。 可能还要提到自旋,它在等待时不释放CPU,适用于短时间的等待。这些都需要分门别类地整理,确保覆盖用户可能关心的各个方面。 最后,结合用户提供的引用,引用[2]中的上下文概念在Go语言中与Goroutine相关,可能涉及在协程同步中的应用,比如互斥在Goroutine中的使用。需要将这些内容整合到回答中,确保引用正确且自然。</think>### 分类与类型(IT上下文) 在计算机科学中,(Lock)是实现并发控制和资源访问同步的核心机制。根据应用场景、实现方式和行为特性,可分为以下几类: --- #### 一、按作用范围分类 1. **数据库** - **行级(Row-level Lock)** 定数据库表中的单行数据,适用于高并发场景下的细粒度控制,例如MySQL的InnoDB引擎[^3]。 - **表级(Table-level Lock)** 定整张表,适用于批量操作或低并发场景,如MySQL的MyISAM引擎。 - **页级(Page-level Lock)** 定数据库页(一组连续的行),平衡行级和表级的开销。 2. **编程语言级** - **互斥(Mutex)** 确保同一时间仅一个线程访问共享资源,例如Go语言中的`sync.Mutex`[^2]。 ```go var mu sync.Mutex mu.Lock() defer mu.Unlock() ``` - **读写(Read-Write Lock)** 允许多个读操作并行,但写操作独占,如Java的`ReentrantReadWriteLock`。 --- #### 二、按行为特性分类 1. **排他(Exclusive Lock, X)** 事务持有时,其他事务无法读取或修改资源,适用于写操作[^1]。 2. **共享(Shared Lock, S)** 允许多个事务同时读取资源,但禁止修改,适用于读操作。 3. **意向(Intention Lock)** 数据库层级,声明事务将在更细粒度上加(如行级),用于优化冲突检测。 --- #### 三、按实现机制分类 1. **悲观(Pessimistic Lock)** 假设资源竞争激烈,操作前先加(如数据库的`SELECT ... FOR UPDATE`)。 2. **乐观(Optimistic Lock)** 假设冲突较少,通过版本号或时间戳实现无检测,例如CAS(Compare-and-Swap)操作。 --- #### 四、按系统层级分类 1. **操作系统级** - **自旋(Spinlock)** 线程在等待时不释放CPU,适用于短时间等待的场景(如Linux内核)。 - **信号量(Semaphore)** 控制对多个同类资源的访问,通过计数器实现。 2. **分布式** - 基于Redis的分布式(如RedLock算法)。 - 基于ZooKeeper的临时顺序节点实现。 --- #### 五、特殊类型 1. **死(Deadlock)** 多个互相等待导致系统僵局,需通过超时机制或死检测解决。 2. **递归(Reentrant Lock)** 允许同一线程重复获取,避免自问题,如Java的`ReentrantLock`。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值