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

江门建设网站自媒体135软件

江门建设网站,自媒体135软件,石家庄视频优化公司,广告设计图片赏析在多线程和分布式系统中#xff0c;数据一致性是一个核心问题。锁机制作为解决并发冲突的重要手段#xff0c;被广泛应用于各种场景。乐观锁和悲观锁是两种常见的锁策略#xff0c;它们在设计理念、实现方式和适用场景上各有特点。本文将深入探讨乐观锁和悲观锁的原理、实现…         在多线程和分布式系统中数据一致性是一个核心问题。锁机制作为解决并发冲突的重要手段被广泛应用于各种场景。乐观锁和悲观锁是两种常见的锁策略它们在设计理念、实现方式和适用场景上各有特点。本文将深入探讨乐观锁和悲观锁的原理、实现、优缺点以及具体的应用实例并结合代码进行详细讲解帮助读者更好地理解和应用这两种锁机制。 目录 一、锁的基本概念 二、悲观锁 一悲观锁的基本概念 二悲观锁的特点 三悲观锁的实现方式 1. 数据库中的悲观锁 2. Java中的悲观锁 四悲观锁的优缺点 三、乐观锁 一乐观锁的基本概念 二乐观锁的特点 三乐观锁的实现方式 1. 基于版本号的乐观锁 2. 基于时间戳的乐观锁 四乐观锁的优缺点 四、乐观锁与悲观锁的对比 一锁机制 二性能 三适用场景 五、总结 一、锁的基本概念 在并发编程中锁是一种用于控制多个线程对共享资源访问的机制。锁的主要目的是确保在同一时间只有一个线程能够访问共享资源从而避免数据竞争和不一致问题。锁的实现方式多种多样但其核心思想是通过某种机制来限制对共享资源的并发访问。 二、悲观锁 一悲观锁的基本概念 悲观锁是一种基于“悲观”假设的锁机制。它认为在并发环境中多个线程对共享资源的访问很可能会发生冲突因此在访问共享资源之前会先对资源进行加锁。只有获得锁的线程才能访问资源其他线程必须等待锁释放后才能继续执行。悲观锁的核心思想是“宁可错杀一千不可放过一个”通过严格的锁机制来保证数据的一致性。 二悲观锁的特点 强一致性悲观锁通过加锁机制严格限制对共享资源的并发访问能够确保在任何时候只有一个线程能够修改资源从而保证数据的强一致性。高安全性由于悲观锁在访问资源之前会先加锁因此可以有效避免数据竞争和并发冲突适用于对数据一致性要求较高的场景。性能瓶颈悲观锁的加锁和解锁操作会增加系统开销尤其是在高并发场景下锁的争用可能导致线程阻塞降低系统的性能。适用场景悲观锁适用于写操作较多、数据竞争激烈的场景例如数据库事务中的行锁和表锁。 三悲观锁的实现方式 悲观锁可以通过多种方式实现常见的有基于数据库的锁机制和基于Java同步原语的锁机制。 1. 数据库中的悲观锁 在数据库中悲观锁可以通过SELECT ... FOR UPDATE语句实现。该语句会在查询数据时对数据行加锁其他事务必须等待锁释放后才能对该行数据进行操作。 -- 查询并锁定一行数据 SELECT * FROM users WHERE id 1 FOR UPDATE; FOR UPDATE该子句的作用是锁定查询结果中的行防止其他事务对该行数据进行修改。 在Java中可以通过JDBC操作数据库来实现悲观锁。以下是一个简单的示例代码 import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException;public class PessimisticLockExample {public static void main(String[] args) {Connection connection null;PreparedStatement preparedStatement null;ResultSet resultSet null;try {// 获取数据库连接connection DriverManager.getConnection(jdbc:mysql://localhost:3306/test, root, password);// 设置事务为非自动提交connection.setAutoCommit(false);// 查询并锁定一行数据String sql SELECT * FROM users WHERE id ? FOR UPDATE;preparedStatement connection.prepareStatement(sql);preparedStatement.setInt(1, 1);resultSet preparedStatement.executeQuery();if (resultSet.next()) {// 获取锁定的数据String name resultSet.getString(name);System.out.println(Locked user: name);// 模拟业务逻辑处理Thread.sleep(5000);// 更新数据String updateSql UPDATE users SET name ? WHERE id ?;preparedStatement connection.prepareStatement(updateSql);preparedStatement.setString(1, New Name);preparedStatement.setInt(2, 1);preparedStatement.executeUpdate();// 提交事务connection.commit();}} catch (SQLException | InterruptedException e) {e.printStackTrace();try {// 回滚事务if (connection ! null) {connection.rollback();}} catch (SQLException ex) {ex.printStackTrace();}} finally {// 关闭资源try {if (resultSet ! null) {resultSet.close();}if (preparedStatement ! null) {preparedStatement.close();}if (connection ! null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}} } 代码说明 使用SELECT ... FOR UPDATE语句查询并锁定数据行。 设置事务为非自动提交模式确保在事务提交之前其他事务无法对该行数据进行修改。 在锁定数据后模拟业务逻辑处理如Thread.sleep(5000)然后更新数据并提交事务。 如果发生异常回滚事务并释放资源。 2. Java中的悲观锁 在Java中悲观锁可以通过java.util.concurrent.locks包中的Lock接口及其实现类如ReentrantLock来实现。ReentrantLock提供了比内置锁synchronized更灵活的锁操作例如尝试锁定tryLock、设置超时时间tryLock(long timeout, TimeUnit unit)等。 以下是一个使用ReentrantLock实现悲观锁的示例代码 import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockExample {private final Lock lock new ReentrantLock();public void doSomething() {lock.lock(); // 加锁try {// 模拟业务逻辑System.out.println(Thread Thread.currentThread().getName() is doing something.);Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock(); // 释放锁}}public static void main(String[] args) {ReentrantLockExample example new ReentrantLockExample();// 创建多个线程访问共享资源Thread t1 new Thread(example::doSomething, Thread-1);Thread t2 new Thread(example::doSomething, Thread-2);t1.start();t2.start();} } 代码说明 使用ReentrantLock的lock()方法加锁unlock()方法释放锁。 在try块中执行业务逻辑确保在异常情况下能够通过finally块释放锁。 多个线程访问共享资源时只有获得锁的线程能够执行doSomething方法其他线程必须等待锁释放。 四悲观锁的优缺点 优点 数据一致性高悲观锁通过严格的锁机制确保数据的一致性适用于对数据一致性要求较高的场景。实现简单悲观锁的实现相对简单尤其是在数据库层面通过SELECT ... FOR UPDATE语句即可实现。 缺点 性能瓶颈悲观锁的加锁和解锁操作会增加系统开销尤其是在高并发场景下锁的争用可能导致线程阻塞降低系统的性能。资源利用率低由于悲观锁限制了并发访问可能导致资源利用率较低尤其是在读操作较多的场景下。 三、乐观锁 一乐观锁的基本概念 乐观锁是一种基于“乐观”假设的锁机制。它认为在并发环境中多个线程对共享资源的访问发生冲突的概率较低因此在访问资源时不加锁而是通过其他机制如版本号或时间戳来检测数据是否被其他线程修改。如果检测到数据被修改则放弃当前操作并重试。乐观锁的核心思想是“先做事再检查”通过减少锁的使用来提高系统性能。 二乐观锁的特点 高性能乐观锁减少了锁的使用降低了锁的开销适用于读操作较多、写操作较少的场景能够显著提高系统的性能。资源利用率高乐观锁允许多个线程并发访问共享资源提高了资源的利用率。实现复杂乐观锁的实现相对复杂需要通过版本号或时间戳等机制检测数据是否被修改。适用场景乐观锁适用于读操作较多、写操作较少的场景例如缓存系统、分布式系统中的数据一致性控制。 三乐观锁的实现方式 乐观锁可以通过版本号Version Number或时间戳Timestamp来实现。以下分别介绍这两种实现方式。 1. 基于版本号的乐观锁 基于版本号的乐观锁通过为每个数据项添加一个版本号字段来实现。每次修改数据时版本号加1。在更新数据时会检查版本号是否发生变化。如果版本号发生变化说明数据被其他线程修改过当前操作需要重试。以下是一个基于版本号的乐观锁的实现示例 import java.util.concurrent.atomic.AtomicInteger;public class OptimisticLockExample {private int value; // 数据值private AtomicInteger version new AtomicInteger(0); // 版本号public void updateValue(int newValue) {int currentVersion version.get(); // 获取当前版本号while (true) {// 检查版本号是否发生变化if (version.compareAndSet(currentVersion, currentVersion 1)) {// 如果版本号未发生变化更新数据value newValue;System.out.println(Updated value to newValue with version version.get());break;} else {// 如果版本号发生变化重试currentVersion version.get();System.out.println(Version changed, retrying...);}}}public static void main(String[] args) {OptimisticLockExample example new OptimisticLockExample();// 创建多个线程更新数据Thread t1 new Thread(() - example.updateValue(10), Thread-1);Thread t2 new Thread(() - example.updateValue(20), Thread-2);t1.start();t2.start();} } 代码说明 使用AtomicInteger来实现版本号的线程安全操作。 在更新数据时通过compareAndSet方法检查版本号是否发生变化。如果版本号未发生变化则更新数据并增加版本号如果版本号发生变化则重试。 多个线程更新数据时通过版本号机制避免冲突。 2. 基于时间戳的乐观锁 基于时间戳的乐观锁通过为每个数据项添加一个时间戳字段来实现。每次修改数据时更新时间戳。在更新数据时会检查时间戳是否发生变化。如果时间戳发生变化说明数据被其他线程修改过当前操作需要重试。以下是一个基于时间戳的乐观锁的实现示例 import java.util.concurrent.atomic.AtomicLong;public class OptimisticLockWithTimestamp {private int value; // 数据值private AtomicLong timestamp new AtomicLong(System.currentTimeMillis()); // 时间戳public void updateValue(int newValue) {long currentTimestamp timestamp.get(); // 获取当前时间戳while (true) {// 检查时间戳是否发生变化if (timestamp.compareAndSet(currentTimestamp, System.currentTimeMillis())) {// 如果时间戳未发生变化更新数据value newValue;System.out.println(Updated value to newValue with timestamp timestamp.get());break;} else {// 如果时间戳发生变化重试currentTimestamp timestamp.get();System.out.println(Timestamp changed, retrying...);}}}public static void main(String[] args) {OptimisticLockWithTimestamp example new OptimisticLockWithTimestamp();// 创建多个线程更新数据Thread t1 new Thread(() - example.updateValue(10), Thread-1);Thread t2 new Thread(() - example.updateValue(20), Thread-2);t1.start();t2.start();} } 代码说明 使用AtomicLong来实现时间戳的线程安全操作。 在更新数据时通过compareAndSet方法检查时间戳是否发生变化。如果时间戳未发生变化则更新数据并更新时间戳如果时间戳发生变化则重试。 多个线程更新数据时通过时间戳机制避免冲突。 四乐观锁的优缺点 优点 高性能乐观锁减少了锁的使用降低了锁的开销适用于读操作较多、写操作较少的场景能够显著提高系统的性能。资源利用率高乐观锁允许多个线程并发访问共享资源提高了资源的利用率。减少锁竞争乐观锁通过版本号或时间戳机制避免了锁的竞争减少了线程阻塞的可能性。 缺点 实现复杂乐观锁的实现相对复杂需要通过版本号或时间戳等机制来检测数据是否被修改。冲突重试机制乐观锁在检测到冲突时需要重试可能会导致操作失败或性能下降尤其是在高并发写操作较多的场景下。适用场景有限乐观锁适用于读操作较多、写操作较少的场景对于写操作较多的场景其性能优势可能不明显。 四、乐观锁与悲观锁的对比 一锁机制 悲观锁通过加锁机制限制对共享资源的并发访问确保在同一时间只有一个线程能够访问共享资源。 乐观锁不加锁通过版本号或时间戳机制检测数据是否被修改如果检测到冲突则重试。 二性能 悲观锁加锁和解锁操作会增加系统开销尤其是在高并发场景下锁的争用可能导致线程阻塞降低系统的性能。 乐观锁减少了锁的使用降低了锁的开销适用于读操作较多、写操作较少的场景能够显著提高系统的性能。 三适用场景 悲观锁适用于写操作较多、数据竞争激烈的场景例如数据库事务中的行锁和表锁。 乐观锁适用于读操作较多、写操作较少的场景例如缓存系统、分布式系统中的数据一致性控制。 五、总结 乐观锁悲观锁核心思想假设冲突较少先操作再检查冲突通过版本号或时间戳检测数据是否被修改。假设冲突较多通过加锁机制限制对共享资源的并发访问。锁机制不加锁通过版本号或时间戳检测数据是否被修改。加锁通过锁机制限制对共享资源的并发访问。性能读操作多、写操作少时性能高减少锁的开销。写操作多时性能可能受限锁的争用可能导致线程阻塞。资源利用率允许多个线程并发访问资源利用率高。同一时间只有一个线程能访问资源资源利用率低。实现复杂度实现相对复杂需要版本号或时间戳机制。实现相对简单直接通过锁机制实现。适用场景读操作多、写操作少的场景如缓存系统、分布式系统中的数据一致性控制。写操作多、数据竞争激烈的场景如数据库事务中的行锁和表锁。冲突处理发现冲突时重试操作。通过锁机制避免冲突其他线程等待锁释放。数据一致性数据一致性依赖于重试机制可能需要多次尝试。数据一致性高通过锁机制严格保证。并发能力并发能力强允许多个线程同时读取。并发能力弱同一时间只有一个线程能操作。适用语言/框架Java中可通过Atomic类实现版本号机制数据库中可通过版本号字段实现。Java中可通过synchronized或ReentrantLock实现数据库中可通过FOR UPDATE实现。优点性能高、资源利用率高、减少锁竞争。数据一致性高、实现简单、安全性高。缺点实现复杂、冲突时需要重试、适用场景有限。性能瓶颈、资源利用率低、锁竞争可能导致线程阻塞。 乐观锁和悲观锁是两种常见的锁机制它们在设计理念、实现方式和适用场景上各有特点。悲观锁通过加锁机制严格限制对共享资源的并发访问能够确保数据的一致性但可能会导致性能瓶颈。乐观锁通过版本号或时间戳机制检测数据是否被修改减少了锁的使用提高了系统的性能但实现相对复杂且在高并发写操作较多的场景下可能不适用。 在实际应用中选择乐观锁还是悲观锁需要根据具体的业务场景和性能需求来决定。对于写操作较多、数据竞争激烈的场景悲观锁可能是更好的选择而对于读操作较多、写操作较少的场景乐观锁则能够显著提高系统的性能。 通过本文的介绍读者可以更好地理解乐观锁和悲观锁的原理、实现和应用从而在实际开发中合理选择锁机制优化系统的性能和可靠性。
http://www.zqtcl.cn/news/144064/

相关文章:

  • android 旅游网站开发有哪些做伦敦金的网站
  • 物流网站系统php源码seo课程多少钱
  • 手机 网站品牌网站建设 d磐石网络
  • 免费用搭建网站珠海住房和建设局网站
  • 天津做胎儿鉴定网站广州古德室内设计有限公司logo
  • 做爰的最好看的视频的网站简洁型网页
  • 网站一直显示建设中网页制作工具程
  • 苏州seo网站管理网站后台更新后主页没有变化
  • 上海网站公司电话中国电子信息网
  • 合作网站seo在哪里建网站免费
  • 需求网站自动发卡网站开发
  • 用asp做网站span电子商务网站建设的教案
  • 厦门市住房建设网站音乐主题wordpress
  • 小说网站开发文档建站公司用wordpress
  • 自己做手机版网站制作佛山网站建设企划动力
  • 鄂州建设工程造价信息管理网站wordpress 3.9 编辑文章 固定链接 不能编辑
  • asp网站的安全性织梦移动端网站建设
  • 大网站的二级域名哪些平台可以发布产品
  • 旅游网站开发说明书怎么做好销售
  • 网站app生成器天河网站建设服务
  • 南京移动网站建设哪里强新网站建设都需要哪些
  • .net网站制作wordpress配置多语言包
  • 上海源码网站建设公司做短视频的网站都有哪些
  • 网络推广公司联系昔年下拉网络优化seo
  • 网站开发语言识别网站众筹该怎么做
  • 长春做网站公司长春seo公司云主机和云服务器的区别
  • 打开网站乱码怎么做网件路由器登陆网址
  • wordpress 怎么删除主题seo神马网站推广器
  • 番禺网站推广公司宣传片拍摄方案范本
  • 网站建设的公司收费建筑英才网app