公平锁 :按照线程在队列中的排队顺序,先到者先拿到锁
非公平锁 :当线程要获取锁时,先通过两次 CAS 操作去抢锁,如果没抢到,当前线程再加入到队列中等待唤醒。
非公平锁在调用 lock 后,首先就会调用 CAS 进行一次抢锁,如果这个时候恰巧锁没有被占用,那么直接就获取到锁返回了。
非公平锁在 CAS 失败后,和公平锁一样都会进入到 tryAcquire 方法,在 tryAcquire 方法中,如果发现锁这个时候被释放了(state == 0),非公平锁会直接 CAS 抢锁,但是公平锁会判断等待队列是否有线程处于等待状态,如果有则不去抢锁,乖乖排到后面。
公平锁和非公平锁就这两点区别,如果这两次 CAS 都不成功,那么后面非公平锁和公平锁是一样的,都要进入到阻塞队列等待唤醒。
同一线程,在外层方法获取锁后,内层方法自动获取锁。也就是说,线程可以进入任何一个他已经拥有锁同步的方法。
public synchronized void method1(){
method2();
}
public synchronized void method2(){
}
ReentrantLock/synchronized
避免死锁。
class Phone {
synchronized void sendSMS(){
System.out.println(Thread.currentThread().getName()+"---sendSMS");
sendEmail();
}
synchronized void sendEmail(){
System.out.println(Thread.currentThread().getName()+"---sendEmail");
}
}
public class TestArrayList {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendSMS();
},"t1").start();
new Thread(()->{
phone.sendSMS();
},"t2").start();
}
}
class Phone implements Runnable {
Lock lock = new ReentrantLock();
@Override
public void run() {
method1();
}
void method1() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "--method1--lock");
method2();
} finally {
lock.unlock();
System.out.println(Thread.currentThread().getName() + "--method1--unlock");
}
}
void method2() {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "--method2--lock");
} finally {
lock.unlock();
System.out.println(Thread.currentThread().getName() + "--method2--unlock");
}
}
}
public class Main {
public static void main(String[] args) {
Phone phone = new Phone();
Thread t1 = new Thread(phone, "t1");
Thread t2 = new Thread(phone, "t2");
t1.start();
t2.start();
}
}