南宁公司做网站,腾云网建站,杭州网站建设文章,离退休干部网站建设在Java中对于多线程来说#xff0c;锁是一种重要且必不可少的东西#xff0c;那么我们将如何使用以及在什么时候使用什么样的锁呢#xff1f;请各位往下看
悲观锁VS乐观锁
悲观锁#xff1a;
在多线程环境中#xff0c;冲突是非常常见的#xff0c;所以在执行操作之前…在Java中对于多线程来说锁是一种重要且必不可少的东西那么我们将如何使用以及在什么时候使用什么样的锁呢请各位往下看
悲观锁VS乐观锁
悲观锁
在多线程环境中冲突是非常常见的所以在执行操作之前悲观锁就会先把这个资源进行加锁用来保证数据的一致性和完整性阻止了其他线程同一时间对这个数据进行修改但是可能会降低并发性能因为只有等到锁释放其他线程才能继续执行
乐观锁
假设数据一般不会产生冲突所以当数据进行提交更新的时候才会对这个数据进行检测来查看是否发生了并行冲突对比与悲观锁来说是一个更轻量级的锁一般用于读操作更多的时候当数据冲突较少的时候乐观锁能极大的提高并发性能
什么时候用乐观锁比较好什么时候用悲观锁比较好
当读操作远多于写操作的时候我们就可以用乐观锁减少锁的开销提高并发性能。当多个线程频繁的修改同一份数据的时候我们就可以使用悲观锁来保证数据的一致性和完整性避免数据产生冲突。
重量级锁VS轻量级锁
重量级锁
重量级锁依赖于操作系统层面的互斥量mutex来实现这种锁机制涉及到用户态和内核态之间的切换开销较大。当一个线程获取重量级锁的时候这个线程就会独占该锁所保护的资源当其他线程想要获取这把锁的时候就会被阻塞直到锁被释放
轻量级锁
通常依赖于CAS操作来尝试获取锁在冲突较少的情况下轻量级锁可以显著的提高并发性能但是如果多次获取锁失败则可能会变成重量级锁
轻量级锁使用 CAS 操作尝试获取锁尽量避免阻塞线程。重量级锁涉及到线程的阻塞和挂起需要操作系统层面的支持性能开销更大。
自旋锁VS挂起等待锁
自旋锁
当线程加锁失败后不会让线程进入阻塞状态而是在一个循环里面不断获取这把锁直到拿到为止但是假如这把锁被持有的时间很长就会导致CPU资源浪费因为线程会不断的检查这把锁的状态
挂起等待锁
当一个线程已经拥有锁了但是另一个线程尝试获取这个锁时就无法立刻获得此时这个未获取锁的线程就会被挂起并放入等待队列中直到锁被释放相比较于自旋锁来说不用频繁的获取锁的状态挂起等待的时候是不消耗CPU资源的
自旋锁能第一时间获取到锁不涉及线程调度和阻塞但是如果锁持有的时间较长就会消耗大量的CPU挂起等待锁挂起等待是不消耗CPU的适用于数据修改较少的场景并且挂起等待锁是重量级锁的一个典型特征
公平锁VS非公平锁
什么叫做公平是先来后到叫做公平还是概率平均叫做公平其实都是但是对于公平锁来说遵循先来后到的原则是公平而非公平锁则是遵循概率均等
公平锁
当一个线程尝试获取锁的时候会先检查该锁是否可用如果可用则获取锁并继续执行如果不可用则进入等待队列直到锁被释放按照进入等待队列的顺序拿到锁并使用
非公平锁
非公平锁会先检查当前的锁是否可用如果可用则获取锁并继续执行如果不可用则可能会忽略等待队列中的线程并允许当前线程继续获取锁这就导致了可能某些线程会进行长时间的等待从而导致“饿死”
可重入锁和不可重入锁
可重入锁
在Java中synchronized 这个关键字本身就帮我们实现了可重入锁这个功能可重入性同一个线程可以多次获取同一把锁从而减少了死锁的概率
不可重入锁
不允许同一个线程多次获取同一把锁如果一个线程试图再次获取它所持有的锁此时就会导致死锁
读写锁
读锁
允许多个线程同时进行读操作适用于读多写少的场景提高并发性能
写锁
只允许一个线程进行读操作一个线程进行写操作
读加锁和读加锁之间, 不互斥写加锁和写加锁之间, 互斥读加锁和写加锁之间, 互斥