【第22期】观点:IT 行业加班,到底有没有价值?

线程中的的资源(二)

原创 2015年11月21日 14:41:11

  在有关java中的讨论中,一个常不正确地知识是“原子操作不需要进行同步控制”。原子操作是不能被线程调度机制中断的操作;一旦操作开始,那么它一定可以在可能发生的“上下文切换”之前执行完毕。

  原子性可以应用于除long和double之外的所有基本类型之上的“简单操作”。对于读取和写入这些基本类型变量这样的操作,可以保证它们会被当作不可分的操作来操作内存。但是JVM可以将64位(long和double变量)的读取和写入当作两个分离的32位操作来执行,这就产生了在一个读取和写入操作中间发生上下文切换,从而导致不同的任务可以看到不正确结果的可能性。但是,当你定义Long和double变量时,如果使用volatile关键字,就会会获得原子性。

  volatile关键字还确保了应用中的可视性。如果你将一个域声明为volatile的,那么只要对这个域产生了写操作,那么所有的读操作都能看到这个修改。即便使用了本地缓存,情况也确实如此,volatite域会立即写入到主存中,而读取操作就发生在主存中。

  理解原子性和易变性是不同的概念这一点很重要。
  
  

  基本上,如果一个域可能会被多个任务同时访问,或者这些任务中至少有一个是写入任务那么你就应该把这个域的设置为volatile的。如果你将一个域定义为volatile,那么它就会告诉编译器不要执行任何一处读取和写入操作的优化,这些操作的目的是用线程中的局部变量维护对这个域的精确同步。

  与锁相比,Volatile 变量是一种非常简单但同时又非常脆弱的同步机制,它在某些情况下将提供优于锁的性能和伸缩性。如果严格遵循 volatile 的使用条件 —— 即变量真正独立于其他变量和自己以前的值 —— 在某些情况下可以使用 volatile 代替 synchronized 来简化代码。然而,使用 volatile 的代码往往比使用锁的代码更加容易出错。本文介绍的模式涵盖了可以使用 volatile 代替 synchronized 的最常见的一些用例。遵循这些模式(注意使用时不要超过各自的限制)可以帮助您安全地实现大多数用例,使用 volatile 变量获得更佳性能。

1.临界区-同步控制块;

    synchronized (lock) {

            }

  在进入此段代码前,必须得到lock对象的锁。如果其他线程已经得到这个锁,那么就得等到锁被释放以后,才能进入临界区。通过使用同步控制块,而不是对整个方法进行同步控制,可以使多个任务访问对象的时间性能得到显著提高。当然对于Lock对象来说我们也可以显示地创建临界区和synchronized方法一样。

2.在其他对象上同步:
    

  synchronized块必须给定一个在其上进行同步的对象,并且最合理的方式是,使用其方法正在调用的
当前对象:synchronized(this)。这种方式中,如果获得了synchronized块上的锁,那么该对象其他的synchronized方法和临界区就不能被调用了。因此,如果在this上同步,临界区的效果就会直接缩小在同步的范围内。
  这时候问题就来了:有时必须在另一个对象上同步,但如果你要这么做,就必须确保所有相关的任务都是在同一个对象上同步的。

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

Windows线程创建、退出及资源释放

 可以通过以下几种方法创建一个线程: 1、CreateThread 2、_beginthread 3、_beginthreadex 4、AfxBeginThread ---------...

《Java并发编程实践》学习笔记之二:线程安全性(thread-safe)

  《Java并发编程实践》学习笔

CentOS下找出占用CPU资源最多的线程

1.对这个进程中的所有线程作监视:top -p pid -H IT网,http://www.it.net.cn 2.找到最耗CPU的线程:ps -mp pid -o THREAD,tid,time ...

[.net] 关于.net线程问题总结(二)

[.net] 关于.net线程问题总结(二) 2011年01月03日   经常看到名为BeginXXX和EndXXX的方法,他们是做什么用的?   这是.net的一个异步方法名称规范   .Net在设计的时候为异步编程设计了一个异步编程模型(APM),这个模型不仅是使用.NET的开发人员使用,.Net内部也频繁用到,比如所有的Stream就有BeginRead,EndRead,Socket,WebRequet,SqlCommand都运用到了这个模式,一般来讲,调用BegionXXX的时候,一般会启动一个异步过程去执行一个操作,EndEnvoke可以接收这个异步操作的返回,当

如何解决java线程中的资源共享的问题

更多相关的文章的链接:http://www.cnblogs.com/chenssy/p/4701027.html; 1.资源共享问题的产生:由于需要被访问的资源没有被合理地保护起来,所以在多线程都来访...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)