多线程理解(一)  三大特性

进程、线程和多线程的定义。

  1. 进程:是指一段具有某种独立功能的程序关于某个数据集合的一次运行活动(一段程序的执行过程)。
  2. 线程:单个进程执行中的每个任务就是一个线程。
  3. 多线程:在一个进程中有多个线程共享进程资源,执行任务。

 

多线程的三大特性:

  1. 原子性:线程的一个或者多个操作要么全部执行,而且执行过程不会被打断,要么全部都不执行。
  2. 可见性:可见性是指多个线程访问同一个变量的时候,一个线程修改了这个变量的值,其他线程也可以立刻看到这个修改后的值。Java提供关键字volatile关键字来保证可见性(当一个共享变量被volatile修饰后,它会保证修改的值立即更新到主存中,其他线程如果需要用到这个变量,会到主存中去取,这样保证每个线程读取到的数据都是最新的)。Synchronized和Lock也能保证可见性,Synchronized和Lock保证同一时刻只有一个线程能够获得锁然后执行同步代码,并且在释放锁之前,将变量的值刷新到主存中,因此可以保证可见性。
  3. 有序性:即程序的执行顺序按照代码的先后顺序执行。(在java内存模型中,允许编译器和处理器对指令进行重排序,重排序过程不会影响单线程程序的执行,但是会影响多线程并发执行的正确性)

 

举个栗子解释指令重排序:

对于第5行,可分成三行伪代码

1 memory=allocate();// 分配内存 相当于c的malloc

2 ctorInstanc(memory) //初始化对象

3 instance=memory //设置instance指向刚分配的地址

上面的代码在编译器运行时,可能会出现重排序 从1-2-3 排序为1-3-2

如此在多线程下就会出现问题

例如现在有2个线程A,B

线程A在执行第5行代码时,B线程进来,而此时A执行了 1和3,没有执行2,此时B线程判断instance不为null 直接返回一个未初始化的对象,就会出现问题

而用了volatile,上面的重排序就会在多线程环境中禁止,不会出现上述问题

 

 

在JAVA 里面,可以通过volatile关键字来保证“一定的”有序性,另外也可以通过synchronized和lock来保证代码的有序性。因为synchronized和lock保证同一时间只有一个线程执行一段程序,相当于单线程的执行,所以能够保证有序性。

此外,JAVA的内存模型具有一些先天的“有序性”,既不需要通过任何手段就能够保证有序性,这个通常也称为 happens-before 原则。如果两个操作的执行顺序没法从happens-before原则推导出来,那么就不能保证它们的有序性,虚拟机可以随意将他们进行重排序。

下面就来具体介绍下happens-before原则(先行发生原则):

  • 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作
  • 锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作
  • volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作
  • 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C
  • 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作
  • 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生
  • 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行
  • 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始

 这8条原则摘自《深入理解Java虚拟机》。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值