Java SDK 并发包通过 Lock 和 Condition 两个接口来实现管程,其中 Lock 用于解决互斥问题,Condition 用于解决同步问题。
synchronized和Lock的区别
- 能够响应中断
- 支持超时
- 非阻塞地获取锁 ```java
// 支持中断的API void lockInterruptibly() throws InterruptedException; // 支持超时的API boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // 支持非阻塞获取锁的API boolean tryLock();
而 synchronized 之所以能够保证可见性,也是因为有一条 synchronized 相关的规则:synchronized 的解锁 Happens-Before 于后续对这个锁的加锁<a name="qn90y"></a>### 什么是可重入锁可重入锁就是同一个线程可以重复的获取一把锁 内部实现就是有一个计数器,每次加锁都会加一,减锁会减一,为0的时候就会释放锁。 可以避免死锁<a name="BltES"></a>### 公平锁与非公平锁> 锁都对应着一个等待队列,如果一个线程没有获得锁,就会进入等待队列,当有线程释放锁的时候,就需要从等待队列中唤醒一个等待的线程。如果是公平锁,唤醒的策略就是谁等待的时间长,就唤醒谁,很公平;如果是非公平锁,则不提供这个公平保证,有可能等待时间短的线程反而先被唤醒。🤔🤔🤔**队列是有序的?**<br />**<a name="4myhg"></a>### 用锁的最佳实践> 永远只在更新对象的成员变量时加锁> 永远只在访问可变的成员变量时加锁> 永远不在调用其他对象的方法时加锁> 减少锁的持有时间、减小锁的粒度<br /><a name="E5hb1"></a>### 思考问题以下代码是否会有死锁问题?```javaclass Account {private int balance;private final Lock lock= new ReentrantLock();// 转账void transfer(Account tar, int amt){while (true) {if(this.lock.tryLock()) {try {if (tar.lock.tryLock()) {try {this.balance -= amt;tar.balance += amt;} finally {tar.lock.unlock();}}//if} finally {this.lock.unlock();}}//if}//while}//transfer}
会有活锁的问题
线程多的时候 可能会出现获取不到对方的锁,虽然不会阻塞但是会一直运行下去,解决方法就是获取锁增加随机时间lock.tryLock(随机数,NANOSECONDS)
