当前位置: 首页 > wzjs >正文

百度做的网站和其他网站的区别seo教程自学网

百度做的网站和其他网站的区别,seo教程自学网,seo技术平台,成都系统开发在之前章节我们知道对于并发程序可以确保原子性的方式来进行同步操作。但是同步是否成功还有另一个更为重要的方面:内存可见性。 我们不仅希望防止某个线程使用对象状态而另一个线程在同时修改状态,而且希望确保当一个线程修改了对象的状态其他线程能够…

在之前章节我们知道对于并发程序可以确保原子性的方式来进行同步操作。但是同步是否成功还有另一个更为重要的方面:内存可见性。

我们不仅希望防止某个线程使用对象状态而另一个线程在同时修改状态,而且希望确保当一个线程修改了对象的状态其他线程能够看到发生的状态变化。如果没有同步,那么这种情况就无法实现

可见性

可见性是一个重要属性,对于java内存模型中当不同的线程进行对象的修改时候其他线程并不会立马看见修改后的结果,这是由于java的内存模型机制,每个线程修改后是将值存放到线程的私有内存而不是立马存放到公共内存中,因此对于其他线程来说是不可见的。所以当其他线程读取变量的时候很大可能读取到旧值也就是失效值。因此必须采用同步机制来保证读取到的值是最新值

不仅如此,还可能会出现“重排序”的现象。只要在某个线程中出现重排序的情况,那么就无法保证代码的执行是按照顺序进行执行的

在没有同步的情况下,编译器,处理器等都可能对操作的执行顺序金意想不到的调整。在缺乏足够同步的多线程程序中,要相对内存操作的执行顺序进行判断,几乎无法得到正确的结论

有一种简单的方法就能够避免这一系列复杂的问题--采用同步机制

更加深入的理解同步

在之前的文章中我们说到保证原子性的操作就是使用原子类,synchronized关键字等以锁的方式来保证同一时刻只能有一个线程执行整个操作过程。其实这些锁不仅仅能保证原子性而且还能保证可见性,对于内置锁可以确保某个线程以一种可预测的方式来查看另一个线程的执行结果。当线程A执行某个同步代码块时,线程B随后进入由同一个锁保护的同步代码块,在这种情况可以保证在锁被释放之前A看到的变量值在B获得锁后同样可以由B看到,也就是保证了可见性,如果没有加内置锁则无法保证上述实现

所以,这就是为什么访问某个共享可变变量的时候要求所有的线程都使用同一个锁上同步,就是为了保证某个线程写入变量之后对于后续线程是可见的,否则,如果一个线程在未持有正确锁的情况下读取某个变量,那么读到的可能就是一个失效值。

加锁的含义不仅仅局限于互斥行为,还包括内存可见性。为了确保所有线程都能看到共享变量的最新值,所有执行读操作或者写操作的线程都必须在同一个锁上同步

volatile:

volatile变量是一个轻量级同步关键字,对于volatile修饰的变量线程对其进行的任何操作都能达到可见性,操作后的数据并没有放到寄存器中而是直接赋值给了共享变量因此达到了可见性的效果,同时对于被volatile修饰的变量来说可以禁止指令重排序

volatile相比于synchronized来说更加轻量级对于变量的修改所造成的性能损耗更少,但是volatile修饰的变量一般只用作校验场景,也就是操作复杂度低的场景。原因是volatile无法保证原子性,也就是说无法保证同一时间段只有一个线程去处理数据

所以当且仅当满足以下所有条件的时候使用volatile变量:

1.对变量的写入操作不依赖当前变量的值,或者能本证只有一个线程去更新变量值

2.该变量不会与其他变量一起纳入不变性条件中

3.在访问变量时不需要加锁

逸出:

对于一些对象在不该发布(使得一个对象可以在作用域之外的代码中使用)的时候发布出去就是逸出

一个简单的例子,下属代码:

class Test{private String[] states=new String[]{ "xx","xx"...}public String[] getStates(){return states;}}

上述变量states就属于不安全发布可以理解为逸出。任何调用者都能够修改数组内的值,无论其他线程是否会对已发布的引用执行任何操作都不重要了,因为误用该引用的风险是始终存在的也就是不安全发布。还有一种不安全的发布方式--构造函数发布,对于一些对象来说

class Test{private Integer num;public  Test(){
num=1;
new advance(this);
}}

上述方式就是在构造函数中直接通过this发布本身对象,这样会造成不安全发布因为指令重排序会调换两个代码的位置,即使是写在最后一行的也可能会导致发不出半成品对象

不要在构造过程中使用this引用逸出

所以对于那些不安全的发布或者程序员无意发布的对象称它为逸出,一旦逸出之后就需要使用同步策略来保证线程安全

可能有些人会觉得采用同步方式的代价比较高,有没有一些代价较低的方式依然能达到线程安全的效果呢。答案是有的,下面介绍一些不是采用同步的方式来达到线程安全的方法。

线程封闭:

出现线程安全问题的原因就是多线程中同一时间段会有多个线程访问同样的资源,那么如果仅在单线程内访问数据就不需要同步。这种技术被称为线程封闭,他是实现线程安全的最简单方式之一。

线程封闭技术常用的地方就在JDBC中,JDBC的Connection对象并不是线程安全的对象,但是最终却能正确的使用,原因在于Connection本身在连接池中存放(连接池是同步处理过的),每个线程来到的时候取出一个Connection进行操作处理,处理完毕后归还给连接池。在这整个过程当中实际上都是只有一个线程去操作Connection的这就实现了线程封闭从而无需同步就能完成线程安全

还有一个线程封闭的例子则是ThreadLocal类,这个类能使每个线程与某个值关联起来。ThreadLocal为每个线程都存放着互相独立的副本,因此采用get方法或者set方法操作的时候各个值都是互相隔离的。原理是ThreadLocal本身维护着一个map,key是thread,value则对应一个threadlocal的map。这样每个线程就实现了隔离机制

总的来说线程封闭技术无法通过一些现有的实现类来实现,更多的则是程序员自己的代码设计结合不同的场景来完成线程封闭的技术。

栈封闭:

除了线程封闭之外,还有一种栈封闭技术也能实现线程安全。在栈封闭中只能通过局部变量才能访问对象,这样实现线程安全。局部变量固有的属性就是在封闭的执行线程中,也就是说每个线程都存储着自己的局部变量,因此可以实现线程安全。

不可变对象:

满足线程安全的另一种方式则是不可变对象。不可变对象天然就是线程安全的对象。不可变对象不仅能避免原子性问题,而且如果被final修饰的对象具有可见性的。

当满足以下条件时,对象才是不可变的:

  1. 类声明为 final:防止被继承,避免子类修改其行为。
  2. 所有字段声明为 private 和 final:确保字段不可直接访问,且初始化后不可重新赋值。
  3. 不提供修改字段的方法:不定义 setter 方法,或其他修改内部状态的方法。
  4. 构造器初始化所有字段:确保对象创建时所有状态已完全初始化。
  5. 处理可变对象引用:如果包含对可变对象的引用,确保客户端无法获取或修改该引用。

因此保证线程安全的方法到目前为止有同步,线程封闭,栈封闭,以及不可变对象

http://www.dtcms.com/wzjs/121441.html

相关文章:

  • 网站制作关键百度网络营销app
  • php网站修改主页内容友情链接交易网站源码
  • 海口网站建设加王道下拉搜索引擎推广的基本方法有
  • 网站不同时期的优化工作该怎么做网站模板购买
  • 服装设计公司室内平面图如何优化关键词搜索
  • 国外网站首页设计百度排名优化专家
  • 怎样自己做网站推广百度关键词的费用是多少
  • 广告毕业设计作品网站怎么推广自己的店铺
  • 小公司做网站赚钱吗在线网站建设平台
  • 域名停域免费观看软件电商网站seo优化
  • 如何让搜索引擎快速收录网站微营销
  • wordpress文章分类权限专业seo网络推广
  • 政府部门网站建设app推广员怎么做
  • 哪个网站做h5比较好看网站如何被搜索引擎收录
  • 新开河街做网站公司哪个网站做推广效果好
  • 魔方网站建设互联网广告销售
  • 龙华网站建设网站seo技术能不能赚钱
  • 肇庆高要建设局网站优化大师是什么
  • 政府网站建设问题形成原因分析千锋教育培训怎么样
  • 无代码快速搭建网站蚂蚁bt
  • wordpress元素windows7系统优化工具
  • 新企业在哪里做网站好武汉网站推广公司排名
  • 自己做的网站主页被人篡改国内外搜索引擎大全
  • sql网站的发布流程seo排名赚app最新版本
  • 鞍山市做网站公司全国seo搜索排名优化公司
  • 建设网站一般要多久常见的网站推广方法有哪些
  • 东莞做网站公司有哪些免费网站搭建平台
  • 分析网站的关键词推广有奖励的app平台
  • 微信网站建设价格seo小白入门教学
  • 网站流量怎么提升app营销十大成功案例