线程中的的资源(二)

原创 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上同步,临界区的效果就会直接缩小在同步的范围内。
  这时候问题就来了:有时必须在另一个对象上同步,但如果你要这么做,就必须确保所有相关的任务都是在同一个对象上同步的。

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

相关文章推荐

《C++ Concurrency in Action》读书笔记二 线程之间共享资源

共享线程资源

挂起和恢复线程的资源

  • 2010-07-02 09:07
  • 47KB
  • 下载

进程、线程 :系统资源 与 上下文切换

进程

线程资源问

  • 2012-08-07 10:18
  • 54KB
  • 下载

linux线程资源回收方法

转载:http://blog.csdn.net/skyflying2012/article/details/24655751 在写网络服务器程序时可能需要实现多线程接收多个客户端的数据,我实现方...

java 启动线程的资源

  • 2010-06-21 15:46
  • 59KB
  • 下载

Android中加载网络资源时的优化可使用(线程+缓存)解决

本文逻辑清晰,内容简单实用,主要讲述了1.异步加载图片,2.图片缓存,3.内存优化等业务实现,是一篇很好的学习样例,喜欢的可以收藏转载(注:本文源自网络) Android 中加载网络资源时的优化,基本...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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