Java SDK 并发包通过 Lock 和 Condition 两个接口来实现管程,其中 Lock 用于解决互斥问题,Condition 用于解决同步问题。

synchronized和Lock的区别

  1. 能够响应中断
  2. 支持超时
  3. 非阻塞地获取锁 ```java

// 支持中断的API void lockInterruptibly() throws InterruptedException; // 支持超时的API boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // 支持非阻塞获取锁的API boolean tryLock();

  1. synchronized 之所以能够保证可见性,也是因为有一条 synchronized 相关的规则:synchronized 的解锁 Happens-Before 于后续对这个锁的加锁
  2. <a name="qn90y"></a>
  3. ### 什么是可重入锁
  4. 可重入锁就是同一个线程可以重复的获取一把锁 内部实现就是有一个计数器,每次加锁都会加一,减锁会减一,为0的时候就会释放锁。 可以避免死锁
  5. <a name="BltES"></a>
  6. ### 公平锁与非公平锁
  7. > 锁都对应着一个等待队列,如果一个线程没有获得锁,就会进入等待队列,当有线程释放锁的时候,就需要从等待队列中唤醒一个等待的线程。如果是公平锁,唤醒的策略就是谁等待的时间长,就唤醒谁,很公平;如果是非公平锁,则不提供这个公平保证,有可能等待时间短的线程反而先被唤醒。
  8. 🤔🤔🤔**队列是有序的?**<br />**
  9. <a name="4myhg"></a>
  10. ### 用锁的最佳实践
  11. > 永远只在更新对象的成员变量时加锁
  12. > 永远只在访问可变的成员变量时加锁
  13. > 永远不在调用其他对象的方法时加锁
  14. > 减少锁的持有时间、减小锁的粒度
  15. <br />
  16. <a name="E5hb1"></a>
  17. ### 思考问题
  18. 以下代码是否会有死锁问题?
  19. ```java
  20. class Account {
  21. private int balance;
  22. private final Lock lock
  23. = new ReentrantLock();
  24. // 转账
  25. void transfer(Account tar, int amt){
  26. while (true) {
  27. if(this.lock.tryLock()) {
  28. try {
  29. if (tar.lock.tryLock()) {
  30. try {
  31. this.balance -= amt;
  32. tar.balance += amt;
  33. } finally {
  34. tar.lock.unlock();
  35. }
  36. }//if
  37. } finally {
  38. this.lock.unlock();
  39. }
  40. }//if
  41. }//while
  42. }//transfer
  43. }

会有活锁的问题
线程多的时候 可能会出现获取不到对方的锁,虽然不会阻塞但是会一直运行下去,解决方法就是获取锁增加随机时间lock.tryLock(随机数,NANOSECONDS)