JAVA内存模型 (JMM)和同步以及可见性

本文深入探讨Java内存模型(JMM),解释线程间变量可见性的概念,以及如何通过synchronized和volatile关键字确保数据的一致性和同步。

可见性:
   一般来说,我们对可见性的定义是一个线程对共享变量值的修改,能够被其他线程
及时的看到,那么这个时候我们一般称这个变量是线程间可见的。

那么什么是共享变量?
      一般来讲,如果一个变量在多个线程的工作内存中都存在有副本,那么这个
    变量就是这几个线程的共享变量。

 那么啥是工作内存呢? 这个时候就是我们的JMM登场了。
Java内存模型(JMM)。描述了Java程序中各种线程共享变量的访问规则,以及在JVM中将变量存储到内存和从内存中读取出来变量这样的底层细节。
在多核系统中,处理器一般有一层或多层的缓存,这些的缓存通过加速数据访问,和
降低共享内存在总线上的通讯。来提高cpu性能。
在处理器层面上,内存模型定义了一个充要条件,“让当前的处理器可以看到其他处理器写入到内存的数据”  以及 “其他处理器可以看到当前处理器写入到内存的数据”。

有些处理器有很强的内存模型,能够让所有的处理器在任何时候任何指定的内存地址上都可以看到完全相同的值,而有的处理器内存模型较弱,在这种处理器中,必须需用内存屏障。来刷新本地处理器缓存并使本地处理器无效。目的是为了让当前处理器能够看到其他处理器的写操作或让其他处理器看到当前处理器的写操作。

在JMM中所有的变量都存储在主内存中,且每个线程都有自己独立的工作内存,里面保存着该线程使用到的变量的副本。(其实就是主内存的一份拷贝)




Class Reordering{
  int x=0, y=0;
public void writer(){
   x=1;
   y=2;
  } 
public void reader(){
 int r1=y;
 int  r2=x;
}
 }
如果在并发中执行这段代码, 读取Y变量将会得到2这个值。 因为这个写入比写到X变量更晚一些。 但是如果重排序发生了, 那么就能发生对Y变量的写入操作,读取2个变量
的操作紧随其后,而且写入到x这个操作能发生程序的结果可能是r1=2 r2=0;

当然不管编译器如果进行重排序, 也要遵循as-if-serial语义。

as-if-serial语义的意思是: 无论如何重排序,程序执行的结果应该与代码顺序执行的结果是一样的。 这点我们一般靠java编译器在单线程下做保证。 打个比喻:
int num1=1; //1
int num2=2; //2
int sum=num1+num2;//3

 在单线程的情况下, 第一 第2 他们的顺序是可以进行重排序的, 但是第三行是不行的.
 所在在单线程的情况下, 我上面所讲的霹雳啪啦的一大堆理论等于放屁, 别急我们看下面。

在多个线程访问下, as-if-serial是没有作用的, 按照一般情况,一个线程不会关注其他线程正在做什么。无论其他线程在计算还是在读写, 他都不太关心。 但是等他需要关心
其他线程在做什么的时候, 就需要做一个事情了, 这个事情就是同步!~
从java内存模型的角度讲,没有正确同步的含义是
    1.一个线程中有一个对变量的写操作
     2.另外一个线程对同一个变量有读操作
     3. 而且写操作和读操作没有通过同步保证顺序

当这些规则被违反的时候,我们就说在这个变量上有一个“数据竞争”(data race)。一个有数据竞争的程序就是一个没有正确同步的程序。

java在语言层面支持可见性和同步的方式是通过:
  synchronized, volatile. 来实现的。 其中volatile并不能实现可见性。
我这里说的并没有包括jdk1.5以后加入的并发包。

JMM对synchornized 有二条规定:
 1.线程解锁前,必须把共享变量的最新值刷新到主内存中  
  2.线程加锁时, 将清空工作内存中共享变量的值,从而使用共享变量时需要从
    主内存中重新读取最新的值。

所以在synchronized代码块退出的时候就保证了主内存是最新的值, 在加锁时就保证
 了加载的是最新的值。 现在大家应该知道synchronized 为啥能同步了吧。


其实synchornized 可以保证可见性。 应该会有人很奇怪为啥sync锁还能保证可见性。 下面我来说不可见的原因有哪些。
在多线程环境下能够造成不可见的原因一般有三点:
 1. 线程交叉执行。
 2. 重排序结合线程交叉执行.
3.共享变量没有及时更新

首先synchronized 已经保证了线程交叉执行的正确性,  所以第一条没用。 而关于第二条
嘿嘿嘿,我上面也写了 单线程情况下不管你怎么重排序都要保证结果一致性。 所以也废除。 第三.....  大家应该能猜得到。  

大家是不是觉得stnchronized 很无敌很牛逼了?  其实他也是有缺点的, 不然不会有大名鼎鼎的java.util.concurrent并发包的出现。
  我以我的理解说几点sync的坏处, 第一 synchronized粒度太粗, 而且该关键字没有提供当线程没获取到锁的情况下的超时逻辑, 而且。 我们应该知道, 一个只读变量他在多线程坏境下是安全的, 因为他并不会修改变量的值,所以捏。 sync锁应该给我们提供一个对互斥区域的并发读。 但是很遗憾他并没有。。。。

 volatile 这个关键字,他可以实现内存的可见性, 深入点来讲,其实他就是加入了内存
  屏障和禁止重排序优化来实现的, 所以我上面所说的不完全都是废话..... 当我们
 对volatile变量执行写操作的时候,会在写操作后加入一条store屏障指令,他会把cpu写缓存器的缓存强制写入的主内存中去。

当对volatile变量执行读操作时,会在读操作前加入一条load屏障指令,他呢,也会强制cpu读到主内存中去。

 其实在java内存模型中一共定义了8条操作指令。他们负责和工作内存打交道。具体的指令..... 我忘了...  大家可以查一下。太晚了,很多东西记不起。有空在更新一下。



机械手搬运控制系统中的应用摘要:机械手是在机械化、自动化生产过程中发展起来的一种新型装置。它可在空间抓、放、搬运物体等,动作灵活多样,广泛应用在工业生产和其他领域内。应用PLC控制机械手能实现各种规定的工序动作,不仅可以提高产品的质量与产量,而且对保障人身安全,改善劳动环境,减轻劳动强度,提高劳动生产率,节约原材料消耗以及降低生产成本,有着十分重要的意义。本文以日本三菱FX2N-48MR型的PLC为基础,介绍PLC机械手搬运控制中的应用,并给出了详细的PLC程序设计过程。该程序已在工业机械手中获得了广泛应用,具有稳定、可靠的性能。关键词:PLC·机械手,控制。应用1机械结构和控制要求如图1所示是一个将工件由A处传送到B处的机械手示意图,机械手的上升,下降和左移,右移的执行用双线圈二位电磁阀推动气缸完成。其中上升与下降对应电磁阀的线圈分别为YVl与w2,左行、右行对应电磁阀的线圈分别为YV3与YV4。当某个电磁阀线圈通电,就一直保持现有的机械动作,直到相对的另一线圈通电为止。气动机械手的夹紧,松开的动作由只有一个线圈的两位电磁阀驱动的气缸完成,线圈(YVS)断电夹住工件,线圈(YV5)通电,松开工件,以防止停电时的工件跌落。机械手的工作臂都设有上、下限位和左、右限位的位置开关SQl、SQ2和sQ3、SQ4,夹持装置不带限位开关,它是通过一定的延时来表示其夹持动作的完成。机械手在最上面、最左边且除松开的电磁线圈(YV5)通电外其它线圈全部断电的状态为机械手的原位。机械手的操作面板分布情况如图2所示,机械手具有手动、单步,单周期、连续和回原位五种工作方式,用开关SA进行选择。手动工作方式时,用各操作按钮(SB5、SB6,SB7、SB8、SB9、SBIO、SBll)来点动执行相应的各动作l单步工作方式时,每按一次起动按钮(SB3),向前执行一步动作,单周期工作方式时,机械手在原位,按下起动按钮SB3,自动地执行一个工作周期的动作,最后返回原位(如果在动作过程中按下停止按钮SB4,机械手停在该工序上,再按下起动按钮SB3,则又从该工序继续工作,最后停在原位)j连续工作方式时,机械手在原位,按下起动按钮(SB3)机械手就连续重复进行工作(如果按下停止按钮SB4,机械手运行到原位后停止);返回原位工作方式时,按下。回原位”按钮SBll,机械手自动回到原位状态。2 LC的I/o分配如图3所示为PLC的I/O接线图,选用FX2N·48MR的PLC,系统共有18个输入设备和5个输出设备分别占用PLC的18个输入点和5个输出点。为了保证在紧急情况下(包括PLC发生故障时),能可靠地切断PLC的负载电源,设置了交流接触器KM。在PLC开始运行时按下“电源”按钮SBl,使KM线圈得电并自锁,KM的主触点接通,给输出设备提供电源;出现紧急情况时,按下“急停”按钮SB2,KM触点断开电源。 PLC程序设计3.1程序的总体结构如图4所示为机械手系统的PLC梯形图程序的总体结构,将程序分为公用程序、自动程序、手动程序和回原位程序四个部分,其中自动程序包括单步、单周期和连续工作的程序,这是因为它们的工作都是按照同样的顺序进行,所以将它们合在一起编程更加简单。梯形图中使用跳转指令使得自动程序、手动程序和回原位程序不会同时执行。假设选择。手动”方式,则X0为ON、X1为OFF,此时PLC执行完公用程序后,将跳过动程序到P0处,由于X0常闭触点为断开,故执行“手动程序”,执行到P1处,由于X1常闭触点为闭合,所以又跳过回原位程序到P2处l假设选择分“回原位”方式,则X0为OFF、X1为ON,跳过自动程序和手动程序执行回原位程序,假设选择“单步”或“单周期”或“连续”方式,则X0、X1均为OFF,此时执行完自动程序后,跳过手动程序和回原位程序。3.2各部分程序的设计(1)公用程序公用程序如图5所示,左限位开关X12、上限位开关X10的常开触点和表示机械手松开的Y4的常开触点的串联电路接通时,辅助继电器M0变为ON,表示机械手在原位。公用程序用于自动程序和手动程序相互切换的处理,当系统处于手动工作方式时,必须将除初始步以外的各步对应的辅助继电器(M1I-M18)复位,同时将表示连续工作状态的M1复位,否则当系统从自动工作方式切换到手动工作方式,然后又返回自动
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值