乐观锁和悲观锁都是并发控制的方法,用来解决多个线程同时访问共享资源时可能会出现的数据不一致问题。
悲观锁假设在并发访问的情况下,共享资源很可能会发生冲突,因此在访问共享资源之前先加锁,这样其他线程在访问该资源时就需要等待当前线程释放锁。悲观锁适用于资源竞争激烈的情况,但会导致线程的阻塞和上下文切换,影响程序的性能。
常见的悲观锁实现方式包括:
- synchronized关键字:在Java中,可以使用synchronized关键字实现悲观锁,它可以将一个代码块或方法设为同步代码块,同一时刻只有一个线程可以执行该代码块或方法。
- ReentrantLock:ReentrantLock是Java中提供的可重入锁,可以通过lock()方法获取锁,unlock()方法释放锁。
乐观锁假设在并发访问的情况下,共享资源很可能不会发生冲突,因此在访问共享资源之前不加锁,而是在更新资源时检查资源是否被其他线程更新,如果资源未被更新则进行更新操作,如果资源已被更新则返回失败并重试。乐观锁适用于资源竞争不激烈的情况,可以避免线程的阻塞和上下文切换,提高程序的性能。
常见的乐观锁实现方式包括:
- CAS算法:CAS是Compare And Swap的缩写,它是一种无锁算法,可以在没有锁的情况下实现多线程之间的同步操作。CAS算法使用一个原子操作来实现多个线程之间的同步,它比传统的锁机制更加高效。
- 版本号机制:在数据库中,可以使用版本号机制实现乐观锁。每个数据记录都有一个版本号,当多个线程同时更新一条记录时,只有版本号匹配的线程才能成功更新,否则更新失败。
例如,一个乐观锁的实际例子是在电商系统中,当用户下单时,如果有多个线程同时操作同一件商品的库存,就需要使用乐观锁来避免库存数量出现不一致的情况。使用版本号机制可以对商品库存进行更新,如果版本号匹配,则说明库存没有被其他线程修改,可以进行库存减少操作,如果版本号不匹配,则说明库存已经被其他线程修改,需要重试。