java多线程(二)

接着上一篇继续

Monitor

? 为什么我修改线程状态,要牵扯到Monitor?哦,原来,Thread在操作资源的时候(我们讲java万物皆对象,那么资源就是对象),Thread在操作对象的时候,牵扯到要不要释放对象锁,其他线程能否操作这个对象呢,原来如此。

那么Thread该怎么获取对象的Monitor呢

哎,真难,搞清一个问题,带来一堆问题,继续~!了解一下jdk锁
synchronized
Lock

synchronized

哇擦!这玩意居然是个关键字,没有源码-----真难受,看来有必要学习好C,C++ 把jvm代码看一遍了
这玩意是干什么的?
Synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。
(1)确保线程互斥的访问同步代码
(2)保证共享变量的修改能够及时可见
(3)有效解决重排序问题。

一个个理解,

  1. 确保线程互斥的访问同步代码?
    这个好理解,互斥
  2. 保证共享变量的修改能够及时可见
    共享变量? 可见? 这不就是volatile吗?
  3. 有效解决重排序问题
    重排序?
volatile

当一个共享变量被volatile修饰时,它会保证修改的值立即被更新到主存

WTF? 修饰变量的,还是共享变量?变量是什么?是对象的属性,对象是共享的,那么变量也是共享的,不仅限于static哦
特性:
可见性: 是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的(实时的)。
原子性:原子是世界上的最小单位,具有不可分割性。
有序性:一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的,此规则决定了持有同一个对象锁的两个同步块只能串行执行。同时禁止JVM指令重排序
3个特性都好理解,有个新的东西,指令重排序

指令重排序

在JDK中,JAVA语言为了维持顺序内部的顺序化语义,也就是为了保证程序的最终运行结果需要和在单线程严格意义的顺序化环境下执行的结果一致,程序指令的执行顺序有可能和代码的顺序不一致,这个过程就称之为指令的重排序。指令重排序的意义在于:JVM能根据处理器的特性,充分利用多级缓存,多核等进行适当的指令重排序,使程序在保证业务运行的同时,充分利用CPU的执行特点,最大的发挥机器的性能!

WTF? JVM要不要这么智能,还优化代码执行顺序,出错了怎么办??嗯?你负责啊?得看看有没有必要指令重排序

######## happens-Before法则

应用上面的一句话 : 当一个共享变量被volatile修饰时,它会保证修改的值立即被更新到主存

主存?Thread 和 主存? 什么关系?原来,Thread 在运行的时候都会持有对象的缓存,保证效率,然而对象的实际内容都在主存中保存,其他线程修改了对象并持久化到主存,我这个Thread还没有更新主存,在旧值的情况下继续运行,完蛋,这怎么搞,要出错的节奏啊,所以,volatile 保证了,Thead在读写 volatile 修饰的变量的时候,每次都从主存拿最新的值,nice,但是效率你懂得,

说一说 happens-Before

在JMM中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须存在happens-before关系。

看字面意思,也好理解啊,happens-Before 比如我要修改一个值,那么首先我要获取到这个值,才能去改他,没毛病!
那么指令重排序和happens-Before 有什么关系呢?哦,原来禁止指令重排序就是依靠happens-Before法则,啧啧啧,真有意思啊!

咦! 那么有了volatile 为什么还要有synchronized,扯犊子吗?混淆我吗?不知道程序猿多累吗,还混淆我,
①volatile轻量级,只能修饰变量。synchronized重量级,还可修饰方法
②volatile只能保证数据的可见性,不能用来同步,因为多个线程并发访问volatile修饰的变量不会阻塞。
synchronized不仅保证可见性,而且还保证原子性,因为,只有获得了锁的线程才能进入临界区,从而保证临界区中的所有语句都全部执行。多个线程争抢synchronized锁对象时,会出现阻塞。

WTF synchronized比volatile多了修饰内容,方法?变量?代码块? 还保证有序性?绝对互斥,so,原来如此,

Lock

有了synchronized为什么还要Lock?

synchronized 全是JVM 来操作,获取锁,释放锁
1). 获取锁的线程执行完了该代码块,然后线程释放对锁的占有
2)线程执行发生异常,此时JVM会让线程自动释放锁
一点都不自主,什么时候加锁,靠cpu竞争轮转,我关不了,什么时候什么我都关不了,真难受
Lock 完全自主,手动控制,真香!
1)获取锁。如果锁已被其他线程获取,则进行等待。
2)unLock()去释放锁。

Lock 是java接口,有好多实现类,synchronized是java关键字,全靠JVM,什么死锁啊,全不用关心,JVM帮我做了,Lock就不行了,获取锁,不自觉释放,就会死锁,真蛋疼,所以开手动挡还是需要一定技术的,
来看下Lock实现类

public interface Lock

see ReentrantLock
	Condition
	ReadWriteLock
public class ReentrantLock implements Lock, java.io.Serializable
public interface Condition
public interface ReadWriteLock
ReentrantLock

可重入锁 ---->
/**
* The synchronization state.
*/
private volatile int state;
boolean fair ? 是否是公平锁?----Node? 二叉树?队列? yes 队列?

compareAndSet??? CAS

WTF? Lock居然不是使用Monitor,而是用了CAS

什么是CAS?

Compare And Swap的缩写,翻译过来就是比较并替换。
CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。
更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。

问题?

ABA?A最开始的内存地址是X,然后失效了,有分配了B,恰好内存地址是X,这时候通过CAS操作,却设置成功了

怎么解决? all Compare not Compare one?
真扯,看了代码和资料,发现对比了好多东西。总之就是通过final修饰一个对象,对比,利用final的特性
不写了,深夜了,困了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值