java并发

java 高并发

本文分为两部分,后半部分是对源码部分解读

ConcurrentHashMap

todo

CompletableFuture

todo

源码

1.Thread

1. java的线程状态
 public static enum State {
        NEW,
        RUNNABLE,
        BLOCKED,
        WAITING,
        TIMED_WAITING,
        TERMINATED;

        private State() {
        }
    }
2. 中断

java不支持立刻对线程进行stop操作,suspend操作deprecated,
interrupt操作在线程处于 sleep,wait,join状态时,会抛InterruptedException,中断标志位会设置为false

 //此方法逻辑很明确,宏观效果就是interrupted被设置为false
 public void interrupt() {
        if (this != currentThread()) {
            this.checkAccess();
            synchronized(this.blockerLock) {
                Interruptible b = this.blocker;
                if (b != null) {
                    this.interrupted = true;
                    this.interrupt0();
                    b.interrupt(this);
                    return;
                }
            }
        }

        this.interrupted = true;
        this.interrupt0();
    }
	//判断是否被中断,也就是 interrupted == true,然后设置interrupted == false
    public static boolean interrupted() {
        Thread t = currentThread();
        boolean interrupted = t.interrupted;
        // 这里无锁,
        if (interrupted) {
            t.interrupted = false;
            clearInterruptEvent();
        }

        return interrupted;
    }
	// 检查是否被中断
    public boolean isInterrupted() {
        return this.interrupted;
    }
  • 测试代码
    /**
    可测试,即使中断后,被中断线程也不会立刻stop
    */
    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            public void run() {
                for (int i = 0; i < 500; i++) {
                    System.out.println(Thread.currentThread().getName() + i);
                    if (Thread.currentThread().isInterrupted()) {
                        System.out.println("Interrupted...........");
                    }
                }
            }
        }, "AqsTest");
        t.start();
        try {
            TimeUnit.MILLISECONDS.sleep(8);
            t.interrupt();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
3. 线程阻塞和唤醒机制
- Objectwaitnotify,配合synchroized的对象锁,这两个方法都是native,会从用户态切换至内核态,这里可能是性能瓶颈
   //测试
   public static void main(String[] args) {
        Object lock = new Object();
        // 用这里控制t1和t2的抢占锁顺序,t2先获取锁t1无限等待
        AtomicBoolean isThread1First = new AtomicBoolean(false);
        Thread t1 = new Thread(new Runnable() {
            @SneakyThrows
            public void run() {
                if (!isThread1First.get()) {
                    TimeUnit.SECONDS.sleep(1);
                }
                synchronized (lock) {
                    System.out.println(Thread.currentThread().getName() +" get lock");
                    lock.wait();
                    System.out.println(Thread.currentThread().getName() +" finish");
                }
            }
        }, "thread-1");
        Thread t2 = new Thread(new Runnable() {
            @SneakyThrows
            public void run() {
                synchronized (lock) {
                    System.out.println(Thread.currentThread().getName() +" get lock");
                    TimeUnit.SECONDS.sleep(1);
                    lock.notify();
                    System.out.println(Thread.currentThread().getName() +" finish");
                }
            }
        }, "thread-2");
        t1.start();
        t2.start();
    }

为什么synchronizedwait notify协同使用,主要是和synchronized的锁优化相关,对象监控
64bit的jvm的对象头

|-----------------------------------------------------------------------------------------------------------------|
|                                             Object Header(128bits)                                              |
|-----------------------------------------------------------------------------------------------------------------|
|                                   Mark Word(64bits)               |  Klass Word(64bits)    |      State         |
|-----------------------------------------------------------------------------------------------------------------|
|    unused:25|identity_hashcode:31|unused:1|age:4|biase_lock:0| 01 | OOP to metadata object |      Nomal         |
|-----------------------------------------------------------------------------------------------------------------|
|    thread:54|      epoch:2       |unused:1|age:4|biase_lock:1| 01 | OOP to metadata object |      Biased        |
|-----------------------------------------------------------------------------------------------------------------|
|                        ptr_to_lock_record:62                 | 00 | OOP to metadata object | Lightweight Locked |
|-----------------------------------------------------------------------------------------------------------------|
|                       ptr_to_heavyweight_monitor:62          | 10 | OOP to metadata object | Heavyweight Locked |
|-----------------------------------------------------------------------------------------------------------------|
|                                                              | 11 | OOP to metadata object |    Marked for GC   |
|-----------------------------------------------------------------------------------------------------------------|

- juc包的Condition,也就是AQS的接口,使用上和前者相同

juc的locks包下的Condition接口,具体实现是在 AQS(AbstractQueuedSynchronizer)里的ConditionObject,其中用到了LockSupport

	//测试
 public static void main(String[] args) {

        ReentrantLock lock = new ReentrantLock();
        Condition con = lock.newCondition();
        AtomicBoolean isThread1First = new AtomicBoolean(false);
        Thread t1 = new Thread(new Runnable() {
            @SneakyThrows
            public void run() {
                if (!isThread1First.get()) {
                    TimeUnit.SECONDS.sleep(1);
                }
                try{
                    lock.lock();
                    System.out.println(Thread.currentThread().getName() +" get lock");
                    con.await();
                    System.out.println(Thread.currentThread().getName() +" finish");
                }finally {
                    lock.unlock();
                }
            }
        }, "thread-1");
        Thread t2 = new Thread(new Runnable() {
            @SneakyThrows
            public void run() {
                try {
                    lock.lock();
                    System.out.println(Thread.currentThread().getName() + " get lock");
                    TimeUnit.SECONDS.sleep(1);
                    con.signal();
                    System.out.println(Thread.currentThread().getName() + " finish");
                }finally {
                    lock.unlock();
                }
            }
        }, "thread-2");
        t1.start();
        t2.start();
        System.out.println(System.getProperty("os.name"));
        System.out.println(System.getProperty("sun.arch.data.model"));
    }
- lockSupport

locksuppot对线程挂起和唤醒顺序无要求

public class LockSupport {
	// 这里是 jdk.internal.misc.Unsafe;
	// 之前的Unsafe类是这个sun.misc.Unsafe,JDK9以后已经将sun.misc.Unsafe弃用
	//同时改进了lib文件的存储方式,将sun.misc.Unsafe全部存储在了jdk.unsupported里面
    private static final Unsafe U = Unsafe.getUnsafe();
    // ...

	public static void park() {
        U.park(false, 0L);
    }
  	public static void unpark(Thread thread) {
        if (thread != null) {
            U.unpark(thread);
        }
    }
}
    // 测试
    public static void main(String[] args) {
        AtomicBoolean isThread1First = new AtomicBoolean(true);
        Thread t1 = new Thread(new Runnable() {
            @SneakyThrows
            public void run() {
                if (!isThread1First.get()) {
                    TimeUnit.SECONDS.sleep(1);
                }
                    System.out.println(Thread.currentThread().getName() +" get lock");
                    LockSupport.park();
                    System.out.println(Thread.currentThread().getName() +" finish");
            }
        }, "thread-1");
        Thread t2 = new Thread(new Runnable() {
            @SneakyThrows
            public void run() {
                    System.out.println(Thread.currentThread().getName() + " get lock");
                    TimeUnit.SECONDS.sleep(1);
                    LockSupport.unpark(t1);
                    System.out.println(Thread.currentThread().getName() + " finish");
            }
        }, "thread-2");
        t1.start();
        t2.start();
    }
4.本类
public class Thread implements Runnable {
	// ... 
	// 线程名
    private volatile String name;
    //是否守护
    private boolean daemon;
    // 逻辑
    private Runnable target;
    //线程组
    private ThreadGroup group;
    // 状态枚举
	public static enum State {
        NEW,
        RUNNABLE,
        BLOCKED,
        WAITING,
        TIMED_WAITING,
        TERMINATED;

        private State() {
        }
    }    
}

2.AQS

Node

AQS内部的阻塞队列实际是个双向链表,内部抽象静态类Node,作为基类,其中ConditionNode就是在LockSupport中使用到,Node的实现有 ExclusiveNode (独占) SharedNode(共享) ConditionNode

abstract static class Node {
        volatile Node prev;
        volatile Node next;
        Thread waiter;
        volatile int status;
        private static final long STATUS;
        private static final long NEXT;
        private static final long PREV;

        Node() {
        }

        final boolean casPrev(Node c, Node v) {
            return AbstractQueuedSynchronizer.U.weakCompareAndSetReference(this, PREV, c, v);
        }

        final boolean casNext(Node c, Node v) {
            return AbstractQueuedSynchronizer.U.weakCompareAndSetReference(this, NEXT, c, v);
        }

        final int getAndUnsetStatus(int v) {
            return AbstractQueuedSynchronizer.U.getAndBitwiseAndInt(this, STATUS, ~v);
        }

        final void setPrevRelaxed(Node p) {
            AbstractQueuedSynchronizer.U.putReference(this, PREV, p);
        }

        final void setStatusRelaxed(int s) {
            AbstractQueuedSynchronizer.U.putInt(this, STATUS, s);
        }

        final void clearStatus() {
            AbstractQueuedSynchronizer.U.putIntOpaque(this, STATUS, 0);
        }

        static {
            STATUS = AbstractQueuedSynchronizer.U.objectFieldOffset(Node.class, "status");
            NEXT = AbstractQueuedSynchronizer.U.objectFieldOffset(Node.class, "next");
            PREV = AbstractQueuedSynchronizer.U.objectFieldOffset(Node.class, "prev");
        }
    }
基类
public abstract class AbstractQueuedSynchronizer extends AbstractOwnableSynchronizer implements Serializable {
    private static final long serialVersionUID = 7373984972572414691L;
    static final int WAITING = 1;
    static final int CANCELLED = Integer.MIN_VALUE;
    static final int COND = 2;
    // 懒加载的,如果并发不高,阻塞队列还吃内存没必要
    private transient volatile Node head;
    private transient volatile Node tail;
    // 同步状态
    private volatile int state;
    private static final Unsafe U = Unsafe.getUnsafe();
    private static final long STATE;
    private static final long HEAD;
    private static final long TAIL;
	// ...
	// 核心的 CAS 操作
	 protected final boolean compareAndSetState(int expect, int update) {
        return U.compareAndSetInt(this, STATE, expect, update);
    }
 }

3.ReentrantLock

Lock

首先实现的是 Lock接口


public interface Lock {
    void lock();
	// 等待锁时被中断,抛出异常,线程获取锁时调用的
    void lockInterruptibly() throws InterruptedException;

    boolean tryLock();
	
    boolean tryLock(long var1, TimeUnit var3) throws InterruptedException;

    void unlock();
		/**
		ReentrantLock + Condition await() && signal() 等同于
		Synchronized + Object wait() && notifyAll()
		*/
    Condition newCondition();
}

Sync

ReentrantLock 的内部实现是依赖与Sync ,Sync又是继承AQS,Sync的实现有FairSyncUnFairSync

 abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        Sync() {
        }
		// 此注解用于通知jvm编译器为此方法预留固定的栈槽,减少栈帧的分配
        @ReservedStackAccess
        final boolean tryLock() {
            Thread current = Thread.currentThread();
            int c = this.getState();
            if (c == 0) {
            	//CAS尝试获取锁
                if (this.compareAndSetState(0, 1)) {
                	//成功设置当前锁Owner线程
                    this.setExclusiveOwnerThread(current);
                    return true;
                }
                // 可重入
            } else if (this.getExclusiveOwnerThread() == current) {
                ++c;
                // 这里判断是否溢出,感觉有点草率了,不可能重入这么多次吧
                if (c < 0) {
                    throw new Error("Maximum lock count exceeded");
                }

                this.setState(c);
                return true;
            }

            return false;
        }
		// 在 NonFairSync FairSync实现,
        abstract boolean initialTryLock();

        @ReservedStackAccess
        final void lock() {
            if (!this.initialTryLock()) {
                this.acquire(1);
            }

        }

   		/**
   		尝试释放锁
   		*/
        @ReservedStackAccess
        protected final boolean tryRelease(int releases) {
            int c = this.getState() - releases;
            // 判断加锁和解锁是否是同一线程
            if (this.getExclusiveOwnerThread() != Thread.currentThread()) {
                throw new IllegalMonitorStateException();
            } else {
                boolean free = c == 0;
                if (free) {
                	// 设置占有线程 null
                    this.setExclusiveOwnerThread((Thread)null);
                }
				//state = 0;后续isLock()有用
                this.setState(c);
                return free;
            }
        }
				/**
				接下来的方法,语义十分明确
				*/
        protected final boolean isHeldExclusively() {
            return this.getExclusiveOwnerThread() == Thread.currentThread();
        }

        final AbstractQueuedSynchronizer.ConditionObject newCondition() {
            return new AbstractQueuedSynchronizer.ConditionObject(this);
        }

        final Thread getOwner() {
            return this.getState() == 0 ? null : this.getExclusiveOwnerThread();
        }

        final int getHoldCount() {
            return this.isHeldExclusively() ? this.getState() : 0;
        }
		//state == 0 表示未加锁
        final boolean isLocked() {
            return this.getState() != 0;
        }
    }

4.CAS

cas是类似与无锁化,是采用操作系统的原语cmpxchg,cpu执行此指令时,处理器自动锁定总线,禁止其他cpu访问共享变量.执行期间,cpu自动禁止中断,位于java的Unsafe类中

cas的自旋是对性能的损耗,如何量化cas和锁之间的优劣呢?难道是各有千秋😁?其实从 juc对cas的依赖和其高效的性能,应该是cas要优于锁的

package jdk.internal.misc;
public final class Unsafe {
	// 以此类方法compareAndSetXXX作为介绍
	//最终的本地方法,用于比较并设置对象的一个字段。如果当前值等于预期值,则将其设置为新的值,并返回 true;否则不做任何更改并返回 false
  @IntrinsicCandidate
    public final native boolean compareAndSetReference(Object var1, long var2, Object var4, Object var5);
	//执行比较和交换操作,并返回旧值
    @IntrinsicCandidate
    public final native Object compareAndExchangeReference(Object var1, long var2, Object var4, Object var5);

    @IntrinsicCandidate
    //获取操作上加了一个内存屏障,确保了后续对其他变量的读取不会重排序到这个获取操作之前
    public final Object compareAndExchangeReferenceAcquire(Object o, long offset, Object expected, Object x) {
        return this.compareAndExchangeReference(o, offset, expected, x);
    }
	
    @IntrinsicCandidate
    //release 版本,意味着在释放操作上加了一个内存屏障,确保了之前的写操作不会重排序到这个释放操作之后。
    public final Object compareAndExchangeReferenceRelease(Object o, long offset, Object expected, Object x) {
        return this.compareAndExchangeReference(o, offset, expected, x);
    }

    @IntrinsicCandidate
    //一个弱版本的比较并设置方法,它可能不会总是成功,即便预期值正确。它适合于那些可以容忍偶尔失败的应用场景,比如乐观锁
    public final boolean weakCompareAndSetReferencePlain(Object o, long offset, Object expected, Object x) {
        return this.compareAndSetReference(o, offset, expected, x);
    }
    // ....
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lamooo19

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值