随笔 - 1357  文章 - 0  评论 - 1104  阅读 - 1941万

可重入锁 & 不可重入锁

可重入锁指同一个线程可以再次获得之前已经获得的锁,避免产生死锁。

Java中的可重入锁:synchronized 和 java.util.concurrent.locks.ReentrantLock。
1、synchronized 使用方便,编译器来加锁,是非公平锁。
2、ReenTrantLock 使用灵活,锁的公平性可以定制。
3、相同加锁场景下,推荐使用 synchronized。

ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。

锁的实现:
Synchronized是依赖于JVM实现的,而ReenTrantLock是JDK实现的,有什么区别,说白了就类似于操作系统来控制实现和用户自己敲代码实现的区别。前者的实现是比较难见到的,后者有直接的源码可供阅读。

ReenTrantLock实现的原理:
简单来说,ReenTrantLock的实现是一种自旋锁,通过循环调用CAS操作来实现加锁。它的性能比较好也是因为避免了使线程进入内核态的阻塞状态。想尽办法避免线程进入内核的阻塞状态是我们去分析和理解锁设计的关键钥匙。

模拟ReenTrantLock用法:假设有两个线程(A线程、B线程)去调用print(String name)方法,A线程负责打印'zhangsan'字符串,B线程负责打印'lisi'字符串。
a、当没有为print(String name)方法加上锁时,则会产生A线程还没有执行完毕,B线程已开始执行,那么打印出来的name就会出现如下问题。

b、当为print(String name)方法加上锁时,则会产生A执行完毕后,B线程才执行print(String name)方法,达到互斥或者说同步效果。

复制代码
package com.lynch.lock;

/**
 *    ReentrantLock用法
 *
 * @author Lynch
 */
public class ReentrantLockTest {

    public static void main(String[] args) {
        final Outputer outputer = new Outputer();

        //线程A打印zhangsan
        new Thread(() -> {
            while (true) {
                sleep();
                outputer.output("zhangsan");
            }
        }).start();
        
        //线程B打印lisi
        new Thread(() -> {
            while (true) {
                sleep();
                outputer.output("lisi");
            }
        }).start();

    }

    private static void sleep() {
        try {
            Thread.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
复制代码
复制代码
package com.lynch.lock;

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

/**
 * 打印字符
 *
 * @author Lynch
 */
public class Outputer {
    Lock lock = new ReentrantLock();

    public void output(String name) {
        try {
            lock.lock();
            
            int len = name.length();
            for (int i = 0; i < len; i++) {
                System.out.print(name.charAt(i));
            }
            System.out.println();
        } finally {
            lock.unlock();
        }
    }
}
复制代码

 

 

posted on   Ruthless  阅读(3403)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
历史上的今天:
2013-09-25 管理和感悟文章
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示