JUC并发概念介绍

138 阅读3分钟

CAS CAS(Compare and Swap),即比较并替换。CAS的思想很简单:三个参数,一个当前内存值V、旧的预期值A、即将更新的值B,当且仅当预期值A和内存值V相同时,将内存值修改为B并返回true,否则什么都不做,并返回false。 JUC就是java.util.concurrent下面的类包,专门用于多线程的开发。

  • 锁是一种竞争机制,一个方法加锁,一个方法没有加锁,那么普通方法就会先运行,因为它不要去竞争!
  • 被synchornized修饰的同步方法,锁的对象是方法的调用者。谁先调用,谁先执行!
  • 被synchronized修饰和static修饰的方法,锁的对象是类的class对象,唯一的! 根据锁的添加到Java中的时间,Java中的锁,可以分为"同步锁"和"JUC包中的锁"。

同步锁

即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁。Java 1.0版本中就已经支持同步锁了。

  同步锁的原理是,对于每一个对象,有且仅有一个同步锁;不同的线程能共同访问该同步锁。但是,在同一个时间点,该同步锁能且只能被一个线程获取到。这样,获取到同步锁的线程就能进行CPU调度,从而在CPU上执行;而没有获取到同步锁的线程,必须进行等待,直到获取到同步锁之后才能继续运行。这就是,多线程通过同步锁进行同步的原理!

JUC包中的锁

相比同步锁,JUC包中的锁的功能更加强大,它为锁提供了一个框架,该框架允许更灵活地使用锁,只是它的用法更难罢了。

JUC包中的锁包括:Lock接口,ReadWriteLock接口,LockSupport阻塞原语,Condition条件, AbstractOwnableSynchronizer/AbstractQueuedSynchronizer/AbstractQueuedLongSynchronizer三个抽象类,ReentrantLock独占锁,ReentrantReadWriteLock读写锁。

AbstractQueuedSynchronizer就是被称之为AQS的类,它是一个非常有用的超类,可用来定义锁以及依赖于排队阻塞线程的其他同步器;

ReentrantLock,ReentrantReadWriteLock,CountDownLatch,CyclicBarrier和Semaphore等这些类都是基于AQS类实现的。

AbstractQueuedLongSynchronizer 类提供相同的功能但扩展了对同步状态的 64 位的支持。两者都扩展了类 AbstractOwnableSynchronizer(一个帮助记录当前保持独占同步的线程的简单类)。

各种锁的理解

Lock接口的所有实现类

// 可重入锁(普通锁)
ReentrantLock
// 读锁
ReentrantReadWriteLock.ReadLock
// 写锁
ReentrantReadWriteLock.WriteLock

Lock锁的用法

// 以可重入锁为例
Lock lock = new ReentrantLock();
// 加锁
lock.lock();
try{
    // 业务代码
}catch(){
    
}finally{
    // 解锁
    lock.unlock();
}

ReentrantLock

// 无参构造方法(默认非公平锁)
public ReentrantLock() {
	sync = new NonfairSync();
}

public ReentrantLock(boolean fair) {
	sync = fair ? new FairSync() : new NonfairSync();
}

  1. 公平锁,非公平锁 公平锁:非常公平,不能插队,必须先来后到

非公平锁:非常不公平,允许插队,可以改变顺序(ReentrantLock锁默认为非公平锁)

  1. 可重入锁 拿到了外面的锁后,就可以拿到里面的锁了(里面的锁是自动获得的)

3.Synchonized 锁

4.Lock 锁:

  • lock锁必须配对,相当于lock和 unlock 必须数量相同;
  • 在外面加的锁,也可以在里面解锁;在里面加的锁,在外面也可以解锁;
  1. 自旋锁spinlock

  2. 死锁