网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.SSO各产品单点登录的简单实现.
.SimpleXmlEditor项目立项.
.Struts应用实例:Helloapp应用.
.利用RMI实现JAVA分布式应用.
.osworkflow源码分析(一).
.使用Java开发计算器(二).
.为系统添加新字体和中文显示.
.Hibernate入门 - Transaction.
.浅析数据源在JDBC中的应用.
.java 类型提升的约定.
.JAVA学习笔记swingJFrame窗口学习.
.测试实践:Eclipse 之 JUnit.
.Eclipse快速上手指南(4).
.dom规范和在java中的实现 sunmin.
.表单递交合法性检测 - 只接受数字.
.用NetBeans平台开发J2ME游戏实例.
.java分页源码.
.JBoss技术支持文档(二).
.Java 技巧:用 Java 保存位图文件.
.Java Applet的应用技巧(1).

java线程简介(同步详细信息)

发表日期:2008-1-5



  1、互斥
  
  
  在共享对数据的访问中,我们讨论了 synchronized 块的特征,并在实现典型互斥锁(即,互斥或临界段)时说明了它们,其中每次只有一个线程可以执行受给定锁保护的代码块。
  
  互斥是同步所做工作的重要部分,但同步还有其它几种特征,这些特征对于在多处理器系统上取得正确结果非常重要。
  
  2、可见性
  
  
  除了互斥,同步(如 volatile)强制某些可见性约束。当对象获取锁时,它首先使自己的高速缓存无效,这样就可以保证直接从主内存中装入变量。
  
  同样,在对象释放锁之前,它会刷新其高速缓存,强制使已做的任何更改都出现在主内存中。
  
  这样,会保证在同一个锁上同步的两个线程看到在 synchronized 块内修改的变量的相同值。
  
  
  3、什么时候必须同步?
  
  
  要跨线程维护正确的可见性,只要在几个线程之间共享非 final 变量,就必须使用 synchronized(或 volatile)以确保一个线程可以看见另一个线程做的更改。
  
  可见性同步的基本规则是在以下情况中必须同步:
  
  读取上一次可能是由另一个线程写入的变量
  写入下一次可能由另一个线程读取的变量
  
  4、用于一致性的同步
  
  
  除了用于可见性的同步,从应用程序角度看,您还必须用同步来确保一致性得到了维护。当修改多个相关值时,您想要其它线程原子地看到这组更改 — 要么看到全部更改,要么什么也看不到。这适用于相关数据项(如粒子的位置和速率)和元数据项(如链表中包含的数据值和列表自身中的数据项的链)。
  
  考虑以下示例,它实现了一个简单(但不是线程安全的)的整数堆栈:
  
  
  public class UnsafeStack {
   public int top = 0;
   public int[] values = new int[1000];
  
   public void push(int n) {
   values[top++] = n;
   }
  
   public int pop() {
   return values[--top];
   }
  }
  
  5、递增共享计数器
  
  
  通常,假如正在保护一个基本变量(如一个整数),有时只使用 volatile 就可以侥幸过关。但是,假如变量的新值派生自以前的值,就必须使用同步。为什么?考虑这个类:
  
  
  public class Counter {
   private int counter = 0;
  
   public int get() { return counter; }
   public void set(int n) { counter = n; }
   public void increment() {
   set(get() + 1);
   }
  }
  
  
  当我们要递增计数器时,会发生什么?请看 increment() 的代码。它很清楚,但不是线程安全的。假如两个线程试图同时执行 increment(),会发生什么?计数器也许会增加 1,也许增加 2。令人惊异的是,把 counter 标记成 volatile 没有帮助,使 get() 和 set() 都变成 synchronized 也没有帮助。
  
  设想计数器是零,而两个线程同时执行递增操作代码。这两个线程会调用 Counter.get(),并且看到计数器是零。现在两个线程都对它加一,然后调用 Counter.set()。假如我们的计时不太凑巧,那么这两个线程都看不到对方的更新,即使 counter 是 volatile,或者 get() 和 set() 是 synchronized。现在,即使计数器递增了两次,得到的值也许只是一,而不是二。
  
  要使递增操作正确运行,不仅 get() 和 set() 必须是 synchronized,而且 increment() 也必需是 synchronized!否则,调用 increment() 的线程可能会中断另一个调用 increment() 的线程。假如您不走运,最终结果将会是计数器只增加了一次,不是两次。同步 increment() 防止了这种情况的发生,因为整个递增操作是原子的。
  
  当循环遍历 Vector 的元素时,同样如此。即使同步了 Vector 的方法,但在循环遍历时,Vector 的内容仍然会更改。假如要确保 Vector 的内容在循环遍历时不更改,必须同步整个代码块。
  
  6、不变性和 final 字段
  
  
  许多 Java 类,包括 String、Integer 和 BigDecimal,都是不可改变的:一旦构造之后,它们的状态就永远不会更改。假如某个类的所有字段都被声明成 final,那么这个类就是不可改变的。(实际上,许多不可改变的类都有非 final 字段,用于高速缓存以前计算的方法结果,如 String.hashCode(),但调用者看不到这些字段。)
  
  不可改变的类使并发编程变得非常简单。因为不能更改它们的字段,所以就不需要担心把状态的更改从一个线程传递到另一个线程。在正确构造了对象之后,可以把它看作是常量。
  
  同样,final 字段对于线程也更友好。
上一篇:Java多线程编程 人气:900
下一篇:java线程简介(其它线程API详细信息) 人气:665
浏览全部Java的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐