锁相关知识

一、锁

1、悲观锁与乐观锁

(1)悲观锁

  • 对于同一个数据的并发操作,悲观锁认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改。Java中,synchronized关键字和Lock的实现类都是悲观锁

(2)乐观锁

  • 在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试)。Java中,典型的乐观锁是CAS,Java原子类中的递增操作就通过CAS自旋实现的

(3)CAS

  • compare and swap(比较与交换),是一种有名的无锁算法。CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。一般情况下是一个自旋操作,即不断的重试

2、公平锁与非公平锁

(1)公平锁

  • 指多个线程按照申请锁的顺序来获取锁,线程直接进入队列中排队,队列中的第一个线程才能获得锁

(2)非公平锁

  • 多个线程加锁时直接尝试获取锁,获取不到才会到等待队列的队尾等待。但如果此时锁刚好可用,那么这个线程可以无需阻塞直接获取到锁,所以非公平锁有可能出现后申请锁的线程先获取锁的场景。

(3)优缺点

  • 优点:
    • 公平锁:等待锁的线程不会饿死
    • 非公平锁:可以减少唤起线程的开销,整体的吞吐效率高,因为线程有几率不阻塞直接获得锁,CPU不必唤醒所有线程
  • 缺点:
    • 公平锁:整体吞吐效率相对非公平锁要低,等待队列中除第一个线程以外的所有线程都会阻塞,CPU唤醒阻塞线程的开销比非公平锁大
    • 非公平锁:处于等待队列中的线程可能会饿死,或者等很久才会获得锁

二、synchronized方法锁、对象锁、类锁

1、概念

方法锁:类中非静态方法上的锁。注意:方法锁是对象锁,但是对象锁不一定是方法锁
对象锁:类中非静态方法上的锁或者用this或者某一个对象做锁。方法锁也是对象锁
类锁:类中静态方法上的锁或者用XXX.class做锁

2、synchronized的参数放入对象和Class有什么区别

(1)锁住的对象不同

  • 成员方法锁住的实例对象,静态方法锁住的是Class

(2)访问控制不同

  • 如果锁住的是实例,只会针对同一个对象方法进行同步访问,多线程访问同一个对象的synchronized代码块是串行的,访问不同对象是并行的。如果锁住的是类,多线程访问的不管是同一对象还是不同对象的synchronized代码块是都是串行的

三、synchronized的优化


四、volatile、synchronized、Lock之间的区别

volatile:具有可见性、有序性,不具有原子性。
synchronized和Lock:具有可见性、原子性,不具有有序性

五、锁的方法

1、wait、notify和notifyAll方法

wait、notify以及notifyAll都是Object对象的方法,他们必须在被synchronized同步的方法或代码块中调用,否则会报错。
wait:会使该线程进入等待状态(阻塞状态)。
notify:在所有等待线程中随机唤醒一个线程,让它获得锁。
notifyAll:唤醒所有等待的线程,让它们一起竞争锁,最后其中之一获得锁。

注意:notify()或者notifyAll()方法并不是真正释放锁,必须等到synchronized方法或者语法块执行完才真正释放锁

2、join和yield的用法

join:可以使得一个线程在另一个线程结束后再执行。
yield:可以让当前线程从“运行状态”进入到“就绪状态”,然后让所有线程去获取执行权,包括它自己本身。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值