当前位置: 首页 > news >正文

JAVA- 锁机制介绍 进程锁

进程锁

  • 基于文件的锁
  • 基于Socket的锁
  • 数据库锁
  • 分布式锁
    • 基于Redis的分布式锁
    • 基于ZooKeeper的分布式锁

实际工作中都是集群部署,通过负载均衡多台服务器工作,所以存在多个进程并发执行情况,而在每台服务器中又存在多个线程并发的情况,所以在java中锁分为 进程锁和线程锁,本文是对进程锁介绍,进程锁常见如下

基于文件的锁

基于文件的锁(FileLock):多个进程共同访问某个文件,通过锁定一个文件来实现跨进程的互斥
示例代码

public class FileLockExample {
    public static void main(String[] args) {
        try (RandomAccessFile file = new RandomAccessFile("lockfile.lck", "rw");
             FileChannel channel = file.getChannel()) {
            
            // 尝试获取独占文件锁(阻塞直到获取成功)
            FileLock lock = channel.lock();
            try {
                System.out.println("进程获取到文件锁,开始执行临界区操作...");
                Thread.sleep(5000); // 模拟耗时操作
            } finally {
                lock.release();
                System.out.println("进程释放文件锁");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

优点:简单,无需额外依赖。
缺点:文件锁依赖文件系统,不同操作系统可能表现不同;需确保文件路径一致获取字节编码一致,比如windows系统和mac系统默认的字节编码格式就不同

基于Socket的锁

通过绑定端口实现单机进程互斥(不推荐,仅作演示)。
示例代码

import java.net.ServerSocket;

public class PortBasedLockExample {
    private static final int LOCK_PORT = 12345;

    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(LOCK_PORT)) {
            System.out.println("进程获取到端口锁,开始执行临界区操作...");
            Thread.sleep(5000); // 模拟耗时操作
        } catch (Exception e) {
            System.out.println("端口已被占用,其他进程正在运行");
        }
    }
}

优点:无需额外依赖。
缺点:不可靠,易受端口冲突影响;不适用于分布式环境。

数据库锁

多台服务器但是一般是用一个数据库的数据源,通过数据库的行锁或事务实现进程间的互斥。
示例代码(MySQL行锁)

public class DatabaseLockExample {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/mydb";
    private static final String USER = "root";
    private static final String PASS = "password";

    public static void main(String[] args) {
        try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS)) {
            // 开启事务并锁定某一行
            conn.setAutoCommit(false);
            PreparedStatement stmt = conn.prepareStatement(
                "SELECT * FROM locks WHERE lock_name = 'my_lock' FOR UPDATE"
            );
            ResultSet rs = stmt.executeQuery();
            
            if (rs.next()) {
                System.out.println("进程获取到数据库锁,开始执行临界区操作...");
                Thread.sleep(5000); // 模拟耗时操作
            }
            
            conn.commit(); // 提交事务后释放锁
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

优点:适用于分布式环境。
缺点:依赖数据库,需处理连接池和事务超时。

分布式锁

基于Redis的分布式锁

外部协调服务,使用Redis的SETNX命令或RedLock算法实现跨进程锁。
示例代码(Jedis实现)

import redis.clients.jedis.Jedis;
import redis.clients.jedis.params.SetParams;

public class RedisLockExample {
    private static final String LOCK_KEY = "my_distributed_lock";
    private static final String LOCK_VALUE = "locked";
    private static final int LOCK_EXPIRE = 30000; // 锁超时时间(毫秒)

    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        try {
            // 尝试获取锁(SETNX + 超时时间)
            String result = jedis.set(LOCK_KEY, LOCK_VALUE, 
                SetParams.setParams().nx().px(LOCK_EXPIRE));
            
            if ("OK".equals(result)) {
                System.out.println("进程获取到Redis锁,开始执行临界区操作...");
                Thread.sleep(5000); // 模拟耗时操作
            } else {
                System.out.println("获取锁失败,其他进程正在运行");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 释放锁(需使用Lua脚本确保原子性)
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                            "return redis.call('del', KEYS[1]) else return 0 end";
            jedis.eval(script, 1, LOCK_KEY, LOCK_VALUE);
            jedis.close();
        }
    }
}

优点:高性能,适用于分布式系统。
缺点:需处理锁续期、网络分区等问题(推荐使用Redisson库)。

基于ZooKeeper的分布式锁

外部协调服务,利用ZooKeeper的临时有序节点实现进程间协调。
示例代码(Curator框架)

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

public class ZooKeeperLockExample {
    private static final String ZK_ADDRESS = "localhost:2181";
    private static final String LOCK_PATH = "/my_distributed_lock";

    public static void main(String[] args) {
        CuratorFramework client = CuratorFrameworkFactory.newClient(
            ZK_ADDRESS, new ExponentialBackoffRetry(1000, 3));
        client.start();
        
        InterProcessMutex lock = new InterProcessMutex(client, LOCK_PATH);
        try {
            if (lock.acquire(10, java.util.concurrent.TimeUnit.SECONDS)) {
                System.out.println("进程获取到ZooKeeper锁,开始执行临界区操作...");
                Thread.sleep(5000); // 模拟耗时操作
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                lock.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
            client.close();
        }
    }
}

优点:高可靠性,自动处理节点失效。
缺点:依赖ZooKeeper集群,性能低于Redis。

总结
在这里插入图片描述
根据具体场景选择合适的进程锁方案,分布式环境下推荐使用 Redis 或 ZooKeeper 实现!

相关文章:

  • 力扣百大算法题精选【Hard 模式】Top 100 Liked LeetCode
  • conda安装python 遇到 pip is configured with locations that require TLS/SSL问题本质解决方案
  • 城电科技 | 光伏地砖:零碳城市的 太阳能发电“隐形发电站”
  • Muduo网络库实现 [五] - Poller模块
  • 技术回顾day2
  • Linux 2021韩顺平网课笔记:进程管理
  • 树莓派超全系列文档--(19)树莓派配置网络
  • 音乐缓存管理器的性能优化方法分析
  • 相机的曝光和增益
  • CSS中的overflow属性
  • C#从入门到精通(5)
  • 激活函数学习笔记
  • es 3期 第28节-深入掌握集群组建与集群设置
  • 清理redis缓存
  • 架构师论文《论软件质量保证及其应用》
  • 令牌与签名的区别(IT安全/认证机制)
  • blender场景导入Unity的流程(个人总结)
  • net8.0 使用JWT完成登录验证
  • NVR接入录像回放平台EasyCVR视频系统守护舌尖上的安全,打造“明厨亮灶”云监管平台
  • Playwright与Browser Use:领略AI赋能UI自动化测试的魔法魅力
  • “海豚音”依旧,玛丽亚·凯莉本周来沪开唱
  • 湖北石首市委副书记、市长付勇接受审查调查
  • 名帅大挪移提前开启,意属皇马的阿隆索会是齐达内第二吗
  • 深圳两家会所涉卖淫嫖娼各被罚7万元逾期未缴,警方发催告书
  • 东亚社会的“苦难诗学”:从《苦尽柑来遇见你》说起
  • 昆廷·斯金纳:作为“独立自主”的自由