文章目录
并发编程
synchronized
Volatile
18原子类Atomic-xxx
AtomicInteger整数的原子类对象,提供线程安全的加减,自增自减等基本操作
Lock接口 认识和使用
package java.util.concurrent.locks.*
Lock 接口: .tryLock(); .lock(); .unLock();
锁的常见实现类
1.ReentrantLock
2.ReadWriteLock
3.StampedLock
4.AbstractQueueSynchronised(AQS)
**ReentrantLock**
Lock需要显示的获取释放锁,虽然繁琐但是自定义空间更大,代码更灵活。 可以方便的实现公平性,非阻塞的获取锁,能被中断的获取锁,超时获取锁。//自己实现一个锁
public class MyLock implements Lock{
//标志位判断是否拿到锁
private boolean isLock = false;
private Thread lockBy;
private int lockCount;
@Override
public synchronized void lock() {
Thread currentLock = Thread.currentThread();
//如果拿不到锁 就自旋 进入线程等待被唤醒
while(isLock && currentLock!=lockBy) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
isLock = true;
lockBy=currentLock;
lockCount++;
}
@Override
public synchronized void unlock() {
if(lockBy==Thread.currentThread()) {
lockCount--;
//可重入锁,重入次数为0释放锁
if(lockCount==0) {
isLock = false;
//通知线程,为了通知是同一把锁,要加sync
notify();
}
}
}
22AQS源码详解-此处后期开始重看
23-把自己的lock锁用AQS改造
线程间通讯wait notify Condition
任何对象都有等待,通知方法
wait() 对象等待方法,必须是在Sync同步代码块中,然后是锁的实例对象的等待方法。
线程被wait,会释放锁,释放资源进入等待池中挂起。
notify() 随机叫醒一个对象实例等待池中的一个线程
notifyAll()叫醒一个对象实例等待池中的所有线程
生产者消费者模式
Condition接口—》ConditionObject实现类AQS的内部类
对象的【同步队列】,【等待队列】
await() 让线程等待,加到单向链表的等待队列中,不是空队列就添加到最后一个。
signal(): 让线程唤醒,从等待队列中取出第一个。把链表第一个移除,nextNode断掉,第二个变成第一个。–> CompareAndSetWaitStatus(node,NODE.Condition,0)移除的节点把状态从等待设置为同步等待的状态,–> enq(node)再往同步队列中添加–> 然后同步队列就等待竞争CPU资源了。
然后Condition等待队列的特点就是,每New一个condition就是一个Condition队列。
叫醒指定的线程
数据库连接池
34
线程之间通讯-join
线程的加塞,用的比较少,功能其他方案都可以实现。
ThreadLocal
使用:对象作为多个线程的共享资源,那么每个线程去get()set()的时候先获取当前线程。对其他线程不可见。
get() 当前线程获取 ThreadLocalMap 里面存的 Entry e e的key是ThreadLocal,e.value是存的对象;
public T get() {
Thread t = Thread.currentThread();//先获取当前线程
ThreadLocalMap map = getMap(t);//获得ThreadLocalMap
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);//ThreadLocalMap获得Entry
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;//以ThreadLocal实例对象为Key获取Value。
return result;
}
}
return setInitialValue();
}