乐观锁和悲观锁是并发控制的两种不同策略,用于处理多线程环境下的数据访问和修改。它们的主要思想和实现方式有所不同。
-
悲观锁: 悲观锁的基本思想是,在读取或修改数据之前,假设会发生并发冲突,因此会通过加锁来确保在操作期间不会有其他线程干扰。悲观锁的典型代表是数据库中的行锁或表锁,也可以通过 Java 中的 synchronized 关键字来实现。当一个线程获取了悲观锁后,其他线程必须等待该锁的释放,这可能导致并发性能下降。
Java在JDK1.5之前都是靠synchronized关键字保证同步的,这种通过使⽤⼀致的锁定协议来协调对共享状态的访 问,可以确保⽆论哪个线程持有共享变量的锁,都采⽤独占的⽅式来访问这些变量。独占锁其实就是⼀种悲观锁,所以 可以说synchronized是悲观锁。
-
乐观锁: 乐观锁的基本思想是,假设在读取和修改数据时不会发生并发冲突,因此不会立即加锁,而是在提交更新时检查是否有其他线程修改了数据。如果发现有冲突,乐观锁通常采用一些机制来处理,比如重新读取数据、合并更新等。乐观锁的典型代表是版本号控制。在 Java 中,可以使用 CAS(Compare and Swap)操作来实现乐观锁。
乐观锁( Optimistic Locking)其实是⼀种思想。相对悲观锁⽽⾔,乐观锁假设认为数据⼀般情况下不会造成冲突, 所以在数据进⾏提交更新的时候,才会正式对数据的冲突与否进⾏检测,如果发现冲突了,则让返回⽤户错误的信息, 让⽤户决定如何去做。
总的来说,悲观锁倾向于在整个数据操作过程中都持有锁,以避免并发冲突,但可能导致并发性能下降。而乐观锁则倾向于在数据操作之前不加锁,通过检查和处理冲突来实现并发控制,从而提高并发性能。选择哪种锁取决于具体的应用场景和数据访问模式。