乐观锁:
适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升。
悲观锁:
适合写操作多的场景,先加锁可以保证写操作时数据正确。
举例,从日常生活中的卖票场景理解公平锁和非公平锁
class Ticket {
private int number = 50;
//默认用的是非公平锁(false),改为true就是公平锁
private Lock lock = new ReentrantLock();
public void sale() {
lock.lock();
try
{
if(number > 0)
{
System.out.println(Thread.currentThread().getName()+"\t 卖出第: "+(number--)+"\t 还剩下: "+number);
}
}finally {
lock.unlock();
}
}
}
public class SaleTicketDemo {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(() -> { for (int i = 1; i <=55; i++) ticket.sale(); },"a").start();
new Thread(() -> { for (int i = 1; i <=55; i++) ticket.sale(); },"b").start();
new Thread(() -> { for (int i = 1; i <=55; i++) ticket.sale(); },"c").start();
new Thread(() -> { for (int i = 1; i <=55; i++) ticket.sale(); },"d").start();
new Thread(() -> { for (int i = 1; i <=55; i++) ticket.sale(); },"e").start();
}
}


从上边的场景看公平锁和非公平锁存在的问题
默认非公平锁和公平锁存在的意义?
非公平锁能更充分的利用CPU 的时间片,尽量减少 CPU 空闲状态时间。
当采用非公平锁时,1个线程请求锁获取同步状态,然后释放同步状态,因为不需要考虑是否还有前驱节点,所以刚释放锁的线程,在此刻再次获取同步状态的概率就变得非常大,所以就减少了线程的开销。
公平锁保证了排队的公平性, 避免了“锁饥饿”问题。
如何选择非公平锁和公平锁
非公平锁和公平锁源码上的差别

Synchronized 的重入实现原理
产生死锁主要原因
手写一个死锁
final Object objectLockA = new Object();
final Object objectLockB = new Object();
new Thread(() -> {
synchronized (objectLockA)
{
System.out.println(Thread.currentThread().getName()+"\t"+"自己持有A,希望获得B");
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
synchronized (objectLockB)
{
System.out.println(Thread.currentThread().getName()+"\t"+"A-------已经获得B");
}
}
},"A").start();
new Thread(() -> {
synchronized (objectLockB)
{
System.out.println(Thread.currentThread().getName()+"\t"+"自己持有B,希望获得A");
//暂停几秒钟线程
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
synchronized (objectLockA)
{
System.out.println(Thread.currentThread().getName()+"\t"+"B-------已经获得A");
}
}
},"B").start();