SpringBoot实现单机锁和分布式锁

1、使用Java的内置锁机制(单机锁)

Java提供了synchronized关键字和java.util.concurrent.locks.Lock接口来实现锁。

  • synchronized是Java语言内置的关键字,当它被用作修饰一个方法时,该方法在同一时间只能被一个线程访问。
  • Lock接口提供了更灵活的锁机制,包括可重入锁、公平锁、非公平锁等。
private final Lock lock = new ReentrantLock();

public void doSomething() {
    lock.lock();
    try {
        // ... 临界区代码
    } finally {
        lock.unlock();
    }
}

2、使用Redis实现分布式锁

虽然Redis分布式锁通常用于分布式系统中,但也可以用于单机环境。使用Redis的SETNX命令可以实现一个简单的分布式锁。

public class Demo {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public boolean lock(String lockKey) {
        return stringRedisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
    }

    public void unlock(String lockKey) {
        stringRedisTemplate.delete(lockKey);
    }
}

使用Redis实现锁的优点是它可以实现分布式锁,当你的应用需要扩展到多个实例时,这是一个很好的选择。

3、使用第三方库

还有一些第三方库,如Redisson,它提供了丰富的分布式锁实现,包括可重入锁、公平锁、联锁、读写锁等。

import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;

public class DistributedLockDemo {

    @Autowired
    private RedissonClient redissonClient;

    public void test() throws InterruptedException, Throwable {
        String lockKey = "myLock";
        RLock lock = redissonClient.getLock(lockKey);
        try {
            boolean isLock = lock.tryLock(10, 5, TimeUnit.SECONDS);
            if(isLock){
                System.out.println("获取到锁,执行业务逻辑...");
                Thread.sleep(3000);
            }
        } finally {
            // 释放当前线程锁
            if(lock.isHeldByCurrentThread()){
                Tlock.unlock();
            }
        }
    }
}

虽然这些库主要用于分布式环境,但也可以在单机环境中使用。

在选择锁的实现方式时,你需要根据你的应用的具体需求来决定。例如,如果你的应用需要扩展到多个实例,那么你可能需要使用Redis或数据库来实现分布式锁。如果你的应用只会在单个实例中运行,那么Java的内置锁机制可能就足够了。

4、使用数据库实现锁

数据库也可以用来实现锁。你可以创建一个专门的表来存储锁的信息,然后通过插入或更新记录来尝试获取锁。如果记录存在,则获取锁失败;如果记录不存在,则插入一条新记录来获取锁。

@Autowired
private JdbcTemplate jdbcTemplate;

public boolean lock(String lockKey) {
    return jdbcTemplate.update("INSERT INTO lock_table (lock_key) VALUES (?) ON DUPLICATE KEY UPDATE lock_key=lock_key", lockKey) == 1;
}

public void unlock(String lockKey) {
    jdbcTemplate.update("DELETE FROM lock_table WHERE lock_key=?", lockKey);
}
posted @ 2024-03-22 15:09  司码易  阅读(54)  评论(0编辑  收藏  举报