3 深入理解并发编程(下)

1 sychronized内置锁

多个线程同时访问同一个变量,会导致不可预料的结果

 上述代码执行的结果均是 10000+

1.1 对象锁和类锁

对象锁:成员方法上 or 内部同步代码块

类锁:类的静态方法上

注:加锁的对象必须是同一个,否则毫无意义

2 volatile最轻量的通信/同步机制

        不同线程对这个变量进行操作时的可见性(一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的)

        volatile并不保证线程安全(例:volatile int count ... count++ 最终结果仍不可预测)

        适用场景:一个线程写、多个线程读场景

3 等待通知机制

线程通信:

        1 线程A通知线程B

        2 线程B轮询线程A

等待通知机制是个很好的方法:

        线程A调用o.wait();进入等待状态;线程B调用o.notify()或o.notifyAll()方法,线程A收到通知后从o.wait();方法处返回,继续执行

                notify():通知一个在对象上等待的线程,使其从 wait 方法返回

                notifyAll():通知所有等待在该对象上的线程

                wait():调用该方法的线程进入 WAITING 状态

                wait(long):超时等待 n 毫秒

3.1 等待和通知的标准范式

等待方遵循如下原则:
        1 获取对象的锁
        2 如果条件不满足,那么调用对象的 wait()方法,被通知后仍要检查条件
        3 条件满足则执行对应的逻辑

通知方遵循如下原则:
        1 获得对象的锁
        2 改变条件
        3 通知所有等待在对象上的线程

        在调用 wait()、notify()系列方法之前,线程必须要获得该对象的对象级别锁,即只能在同步方法或同步块中调用 wait()方法、notify()系列方法

notify和notifyAll应该用谁?

        尽可能用 notifyall(),谨慎使用 notify(),因为 notify()只会唤醒一个线程

4 CompleteableFuture

        Future仅能拿到一个结果;实际工作中是 1任务组合 2链式调用,引入CompleteableFuture

        Asynsc 表示异步,而 supplyAsync 与 runAsync 不同在于,supplyAsync 异步返回一个结果,runAsync 是 void

        第二个函数第二个参数表示是用我们自己创建的线程池,否则采用默认的ForkJoinPool.commonPool()作为它的线程池

获得结果的方法:
        public T get()
        public T get(long timeout, TimeUnit unit)
        public T getNow(T valueIfAbsent)
        public T join()
        getNow 有点特殊,如果结果已经计算完则返回结果或者抛出异常,否则返回给定的 valueIfAbsent 值
        join 返回计算的结果或者抛出一个 unchecked 异常(CompletionException),它和 get 对抛出的异常的处理有些细微的区别

        关键入参是函数式接口 Function。它的入参是上一个阶段计算后的结果,返回值是经过转化后结果

        关键入参是函数式接口 Consumer。它的入参是上一个阶段计算后的结果,没有返回值

        对上一步的计算结果不关心,执行下一个操作,入参是一个 Runnable 的实例,表示上一步完成后执行的操作

...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值