前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >悲观锁,乐观锁,读写锁,行锁,表锁,自旋锁,死锁,分布式锁,线程同步锁,公平锁,非公平锁分别是什么

悲观锁,乐观锁,读写锁,行锁,表锁,自旋锁,死锁,分布式锁,线程同步锁,公平锁,非公平锁分别是什么

原创
作者头像
小马哥学JAVA
发布2024-07-04 08:58:53
1580
发布2024-07-04 08:58:53

锁机制在并发编程和数据库管理中用于控制对资源的访问,确保数据一致性和系统稳定性。以下是各种锁的解释及其应用场景:

悲观锁(Pessimistic Lock)

  • 原理:假定会发生并发冲突,操作数据时将其锁定,直到事务结束。其他事务在此期间无法对数据进行操作。
  • 应用场景:适用于写多读少,数据冲突概率高的场景。
  • 实现方式:数据库的SELECT ... FOR UPDATE语句可以实现悲观锁。

乐观锁(Optimistic Lock)

  • 原理:假定不会发生并发冲突,操作数据时不加锁,只在提交更新时检查冲突。如果发现冲突,重试操作。
  • 应用场景:适用于读多写少,数据冲突概率低的场景。
  • 实现方式:通常通过版本号或时间戳字段实现。例如,在更新数据时检查版本号是否一致,不一致则重试。

读写锁(Read-Write Lock)

  • 原理:区分读锁和写锁。读锁允许多个线程同时读取,写锁只允许一个线程写入,且写入期间不允许读取。
  • 应用场景:读多写少的场景,提高并发度。
  • 实现方式:Java中的ReentrantReadWriteLock

行锁(Row Lock)

  • 原理:锁定数据库中的一行数据,防止其他事务对同一行数据进行并发操作。
  • 应用场景:需要对单行数据进行高并发操作的场景。
  • 实现方式:数据库的SELECT ... FOR UPDATE语句可以锁定单行记录。

表锁(Table Lock)

  • 原理:锁定整个表,防止其他事务对该表进行并发操作。
  • 应用场景:适用于需要对整个表进行批量操作的场景。
  • 实现方式:数据库的LOCK TABLES语句可以锁定表。

自旋锁(Spin Lock)

  • 原理:当一个线程尝试获取锁但失败时,不是进入休眠状态,而是循环(自旋)等待,直到成功获取锁。
  • 应用场景:锁的持有时间很短的场景,避免线程切换的开销。
  • 实现方式:Java中的Atomic包中的CAS操作(Compare-And-Swap)。

死锁(Deadlock)

  • 原理:两个或多个线程互相等待对方释放资源,导致所有线程都无法继续执行。
  • 解决方案:通过死锁检测和死锁预防算法,如银行家算法、资源申请顺序等。
  • 示例:两个线程A和B,A持有资源1等待资源2,B持有资源2等待资源1,导致互相等待无法继续。

分布式锁(Distributed Lock)

  • 原理:在分布式系统中,确保多个节点对共享资源的互斥访问。
  • 实现方式
    • 数据库实现:通过数据库行锁实现,例如MySQL的SELECT ... FOR UPDATE
    • 缓存实现:通过Redis的setnx命令。
    • Zookeeper实现:使用Zookeeper的临时节点和顺序节点。

线程同步锁(Thread Synchronization Lock)

  • 原理:确保多个线程对共享资源的互斥访问,防止线程间的竞态条件。
  • 实现方式:Java中的synchronized关键字和ReentrantLock

公平锁(Fair Lock)

  • 原理:按照线程请求锁的顺序(FIFO)获取锁,避免某些线程长期得不到锁。
  • 应用场景:需要严格控制锁的获取顺序的场景。
  • 实现方式:Java中的ReentrantLock构造函数可以设置为公平锁。

非公平锁(Non-fair Lock)

  • 原理:不保证线程获取锁的顺序,高效但可能导致某些线程长期得不到锁。
  • 应用场景:对性能要求较高,不严格要求顺序的场景。
  • 实现方式:Java中的synchronized和默认的ReentrantLock

示例代码

以下是各类锁在Java中的简单示例代码:

悲观锁(数据库示例)
代码语言:javascript
复制
sql复制代码-- 悲观锁示例
BEGIN;
SELECT * FROM products WHERE product_id = 1 FOR UPDATE;
-- 进行相关操作...
COMMIT;
乐观锁(Java示例)
代码语言:javascript
复制
java复制代码public boolean updateProduct(Product product) {
    String sql = "UPDATE products SET stock = ?, version = ? WHERE product_id = ? AND version = ?";
    int result = jdbcTemplate.update(sql, product.getStock(), product.getVersion() + 1, product.getProductId(), product.getVersion());
    return result == 1;
}
读写锁(Java示例)
代码语言:javascript
复制
java复制代码ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
Lock readLock = readWriteLock.readLock();
Lock writeLock = readWriteLock.writeLock();

public void readData() {
    readLock.lock();
    try {
        // 读取数据
    } finally {
        readLock.unlock();
    }
}

public void writeData() {
    writeLock.lock();
    try {
        // 写入数据
    } finally {
        writeLock.unlock();
    }
}
自旋锁(Java示例)
代码语言:javascript
复制
java复制代码public class SpinLock {
    private AtomicReference<Thread> owner = new AtomicReference<>();

    public void lock() {
        Thread currentThread = Thread.currentThread();
        while (!owner.compareAndSet(null, currentThread)) {
            // 自旋
        }
    }

    public void unlock() {
        Thread currentThread = Thread.currentThread();
        owner.compareAndSet(currentThread, null);
    }
}
分布式锁(Redis示例)
代码语言:javascript
复制
java复制代码public boolean acquireLock(Jedis jedis, String lockKey, String requestId, int expireTime) {
    String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
    return "OK".equals(result);
}

public boolean releaseLock(Jedis jedis, String lockKey, String requestId) {
    String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                    "return redis.call('del', KEYS[1]) else return 0 end";
    Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
    return "1".equals(result);
}
线程同步锁(Java示例)
代码语言:javascript
复制
java复制代码public synchronized void synchronizedMethod() {
    // 同步代码块
}

public void reentrantLockMethod() {
    ReentrantLock lock = new ReentrantLock();
    lock.lock();
    try {
        // 同步代码块
    } finally {
        lock.unlock();
    }
}
公平锁与非公平锁(Java示例)
代码语言:javascript
复制
java复制代码ReentrantLock fairLock = new ReentrantLock(true);  // 公平锁
ReentrantLock nonFairLock = new ReentrantLock();   // 非公平锁,默认

public void fairLockMethod() {
    fairLock.lock();
    try {
        // 同步代码块
    } finally {
        fairLock.unlock();
    }
}

总结

锁机制在并发编程和数据库管理中扮演着重要角色,选择合适的锁机制可以有效提升系统的并发性能和数据一致性。根据具体应用场景的需求,合理选择和组合锁机制,才能实现高效稳定的系统。

我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 悲观锁(Pessimistic Lock)
  • 乐观锁(Optimistic Lock)
  • 读写锁(Read-Write Lock)
  • 行锁(Row Lock)
  • 表锁(Table Lock)
  • 自旋锁(Spin Lock)
  • 死锁(Deadlock)
  • 分布式锁(Distributed Lock)
  • 线程同步锁(Thread Synchronization Lock)
  • 公平锁(Fair Lock)
  • 非公平锁(Non-fair Lock)
  • 示例代码
    • 悲观锁(数据库示例)
      • 乐观锁(Java示例)
        • 读写锁(Java示例)
          • 自旋锁(Java示例)
            • 分布式锁(Redis示例)
              • 线程同步锁(Java示例)
                • 公平锁与非公平锁(Java示例)
                • 总结
                相关产品与服务
                云数据库 Redis
                腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档