什么是悲观锁?
- 悲观锁是一种基于悲观态度的数据并发控制机制。
- 当前线程去操作数据的时候,总是认为别的线程会去修改数据,所以每次操作数据的时候都会上锁,别的线程去操作数据的时候就会阻塞。
悲观锁有哪些?
- Synchronized
- ReentrantLock
悲观锁的优缺点是啥?
优点:
- 为数据处理的安全提供了保证。
缺点:
- 在效率方面比较低,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会。
- 降低了并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数。
乐观锁的优缺点是啥?
优点:
- 乐观并发控制相信事务之间的数据竞争(datarace)的概率是比较小的,因此尽可能直接做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁。
缺点:
- 但如果直接简单这么做,还是有可能会遇到不可预期的结果,例如两个事务都读取了数据库的某一行,经过修改以后写回数据库,这时就遇到了问题。
什么是乐观锁
悲观锁的实现方式?
- 使用synchronized关键字。在Java中,可以使用synchronized关键字对代码块或方法进行加锁,以确保同一时刻只有一个线程可以访问该资源。
- 使用ReentrantLock类。通过调用ReentrantLock类的lock方法来获得锁,并在finally块中调用unlock方法来释放锁。
- 使用ReadWriteLock类。ReadWriteLock是一种读写分离的锁机制,通过使用读锁和写锁来实现对共享资源的悲观锁控制。读锁允许多个线程同时读取共享资源,而写锁则只能有一个线程进行写操作。
- 使用数据库的锁机制。在分布式系统中,可以借助数据库自身的锁机制来实现悲观锁,例如使用数据库的for update子句来锁定记录。
乐观锁的实现方式?
- CAS机制
- 版本号机制
乐观锁的使用场景?
- 读多写少的应用场景:乐观锁适用于读操作远多于写操作的情况,这样可以提高系统的吞吐量。
- 并发控制:在多用户访问共享资源时,乐观锁通过版本号机制来避免数据冲突,允许多个请求同时访问数据,但通过业务实现锁的功能,而不是直接对数据加锁。
- 代码版本控制:在GIT、SVN、CVS等代码版本控制管理器中,乐观锁的使用可以确保代码的版本一致性。例如,当多个开发者同时修改同一个文件时,乐观锁可以防止未提交的修改被覆盖,从而避免版本冲突。
悲观锁的使用场景?
- 并发写入多、临界区代码复杂、竞争激烈:在这种情况下,悲观锁可以避免多个线程同时修改数据,从而保证数据的一致性和完整性。
- 数据安全性要求高:悲观锁通过在修改数据之前先加锁,可以防止其他线程在数据被修改的过程中访问这些数据,从而提高了数据的安全性。
- 适合于执行时间较长的任务:如果一个任务可能会执行很长时间,并且在此期间可能会发生并发冲突,使用悲观锁可以确保数据在任何时候都不会被其他线程修改。
- 不适合乐观锁的场景:对于那些冲突较少,主要是读取操作,或者虽然读写都很多,但是并发并不激烈的场景,使用悲观锁可能会导致性能问题,因为频繁的加锁和解锁操作会增加系统的开销。
什么是CAS?
- CAS是Compare And Swap的缩写,中文名为比较并交换。这是Java并发实现原子操作的一种方式。它将内存位置的数值与预期数值进行比较,如果相等,则将该内存位置的数值替换为新值;如果不相等,则不执行任何操作。这是一种无锁的解决方案,基于乐观锁的操作,用于保证多线程并发中共享资源的原子性操作。
什么是死锁?
- 死锁是指在多道程序系统中,一组进程中的每一个进程都无限期地等待被该组进程中另一个进程所占用的且永远不会释放的资源,若无外力作用,它们都将无法推进下去,此时系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。