- 浏览: 173286 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
dupeng41255:
问一下,。com的接口 是不是需要注册啊?我调用的时候返回说需 ...
java实现whois域名查询 -
feiyu86:
比喻的非常贴切。。
synchronized方法和代码块的使用 -
罡风笑:
贴结果:CBH 蜀汉 绝顶 刀客
开心一下 你古代的身份。超级好玩~
1、synchronized关键字的作用域有二种:
1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。
2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;
3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;
----------------------------------------------------------------------------
java里面synchronized用法
synchronized的一个简单例子
public class TextThread
{
/**
* @param args
*/
public static void main(String[] args)
{
// TODO 自动生成方法存根
TxtThread tt = new TxtThread();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
new Thread(tt).start();
}
}
class TxtThread implements Runnable
{
int num = 100;
String str = new String();
public void run()
{
while (true)
{
synchronized(str)
{
if (num>0)
{
try
{
Thread.sleep(10);
}
catch(Exception e)
{
e.getMessage();
}
System.out.println(Thread.currentThread().getName()+ "this is "+ num--);
}
}
}
}
}
上面的例子中为了制造一个时间差,也就是出错的机会,使用了Thread.sleep(10)
Java对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了synchronized关键字就可以轻松地解决多线程共享数据同步问题。到底如何?――还得对synchronized关键字的作用进行深入了解才可定论。
总的说来,synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。
在进一步阐述之前,我们需要明确几点:
A.无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。
B.每个对象只有一个锁(lock)与之相关联。
C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
接着来讨论synchronized用到不同地方对代码产生的影响:
假设P1、P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1、P2就都可以调用它们。
1. 把synchronized当作函数修饰符时,示例代码如下:
Public synchronized void methodAAA()
{
//….
}
这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了synchronized关键字的方法。
上边的示例代码等同于如下代码:
public void methodAAA()
{
synchronized (this) // (1)
{
//…..
}
}
(1)处的this指的是什么呢?它指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于object reference。――那个拿到了P1对象锁的线程,才可以调用P1的同步方法,而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造成数据混乱:(
2.同步块,示例代码如下:
public void method3(SomeObject so)
{
synchronized(so)
{
//…..
}
}
这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:
class Foo implements Runnable
{
private byte[] lock = new byte[0]; // 特殊的instance变量
Public void methodA()
{
synchronized(lock) { //… }
}
//…..
}
注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。
3.将synchronized作用于static 函数,示例代码如下:
Class Foo
{
public synchronized static void methodAAA() // 同步的static 函数
{
//….
}
public void methodBBB()
{
synchronized(Foo.class) // class literal(类名称字面常量)
}
}
代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。
记得在《Effective Java》一书中看到过将 Foo.class和 P1.getClass()用于作同步锁还不一样,不能用P1.getClass()来达到锁这个Class的目的。P1指的是由Foo类产生的对象。
可以推断:如果一个类中定义了一个synchronized的static函数A,也定义了一个synchronized 的instance函数B,那么这个类的同一对象Obj在多线程中分别访问A和B两个方法时,不会构成同步,因为它们的锁都不一样。A方法的锁是Obj这个对象,而B的锁是Obj所属的那个Class。
小结如下:
搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程序。
还有一些技巧可以让我们对共享资源的同步访问更加安全:
1. 定义private 的instance变量+它的 get方法,而不要定义public/protected的instance变量。如果将变量定义为public,对象在外界可以绕过同步方法的控制而直接取得它,并改动它。这也是JavaBean的标准实现方式之一。
2. 如果instance变量是一个对象,如数组或ArrayList什么的,那上述方法仍然不安全,因为当外界对象通过get方法拿到这个instance对象的引用后,又将其指向另一个对象,那么这个private变量也就变了,岂不是很危险。 这个时候就需要将get方法也加上synchronized同步,并且,只返回这个private对象的clone()――这样,调用端得到的就是对象副本的引用了。
发表评论
-
Eclipse 中Hibernate tools 的安装和使用
2014-09-23 20:21 714eclipse 远程安装hibernate插件 自动生成mo ... -
Java关键字final、static使用总结
2011-05-24 12:31 938一、final 根据程序上下文环境,Java关键字final ... -
Ubuntu下jdk的几种不用的环境变量配置
2011-04-08 16:30 20711.安装ubuntu下的jdk 到s ... -
快速递归排序及2分查找
2011-04-06 13:55 1224import java.util.Arrays; pub ... -
生产者与消费者例子(多线程wait()与notifyAll应用)
2010-05-25 16:42 999package test; import java.ut ... -
synchronized块及方法应用
2010-05-24 16:02 844package test; class Obj impl ... -
run()外部捕获run()内未捕获的异常
2010-05-24 11:25 909package test; import java.ut ... -
java注解简单应用
2010-05-21 13:38 1632package test; import java.la ... -
enum版本石头剪刀布
2010-05-20 15:24 1097package test; public enum Ou ... -
PowerDesigner建模资料
2010-04-22 01:02 951PowerDesigner建模资料 -
jquery帮助文档
2010-04-21 23:49 1026很有用的帮助文档,见附件 -
Hibernate获取数据方式与缓存使用
2010-04-21 21:55 2339Hibernate获取数据的方式有不同的几种,其与缓存结合使用 ... -
URLConnection的连接、超时、关闭用法总结
2010-04-07 20:54 4825Java中可以使用HttpURLConne ... -
螺旋矩阵(顺时针内转)
2010-03-11 15:47 1454import java.util.Arrays; pub ... -
java面试题库
2010-03-08 00:23 744java的一些常见的题集,学习和面试好帮手 -
Apache tomcat集群总结
2010-03-06 03:33 10871.去掉apache中httpd.conf目录中以下几行的注释 ... -
Apache负载均衡设置方法: mod_proxy
2010-03-06 03:28 1083WebjxCom提示:一般来说 ... -
apache中文文档
2010-03-06 01:40 907apache环境配置中的必要手册 -
kxml源码
2010-03-02 23:17 965非常有用的XML解析器,小巧玲珑 -
FckEditor(java版)配置方法
2009-12-09 13:51 1067一,下载fckeditor包 fckeditor-java- ...
相关推荐
在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。
一、Java基础知识 1.Java有那些基本数据类型,String是不是基本...这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() ...
在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。
9.1 使用collection收集对象 262 9.1.1 认识collection架构 262 9.1.2 具有索引的list 263 9.1.3 内容不重复的set 266 9.1.4 支持队列操作的queue 270 9.1.5 访问对象的iterator 273 9.1.6 排序收集的...
此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),...
对象的使用包括引用对象的成员变量和方法,通过运算符·可以实现对变量的访问和方法的调 用,变量和方法可以通过设定一定的访问权限(见下面的例子)来允许或禁止其它对象对它的 访问。 我们先定义一个类 Point。 例子...
82. 异常的使用方法 98 83. JAVA代码查错 101 83.1. 判断 101 83.2. 判断 102 83.3. 判断 102 83.4. 判断 102 83.5. 判断 102 83.6. 判断 103 83.7. 判断 103 83.8. 判断 103 83.9. 判断 104 83.10. 判断 104 83.11....
此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),...
Overload [java] 方法的重载(不同参数列表的同名方法) [,әuvә'lәud] Override [java] 方法的覆盖(覆盖父类的方法) [,әuvә'raid] polymiorphism[java] 多态 (polymorphism 多形性[,pɒli'mɒ:fizm]) ...
25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................
此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),...
同一个.java文件中是否可以有多个main方法 一个".java"源文件中是否可以包括多个类(不是内部类)?有什么限制? 如何在main方法执行前输出”hello world” java程序的初始化顺序 请说出作用域public,private,...
【基础】Java 中的final关键字有哪些用法? 31 【基础】内部类可以引用它的包含类(外部类)的成员吗?有没有什么限制? 31 【基础】I/O总结 31 【基础】Java中如何实现序列化,有什么意义? 34 【WEB】session与...
Java并发编程实战 本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及...
25 JAVA8 与元数据.................................................................................................................................25 2.4. 垃圾回收与算法 .................................
此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synchronized方法(线程安全),...
1. 简述 private、 protected、 public、 internal 修饰符的访问权限。 答 . private : 私有成员, 在类的内部才可以访问。...47.当一个线程进入一个对象的一个synchronized方法后,其它线程是否可...
141_使用spooldir实现批量收集/ s8 F* }% o- n6 g& a9 w 142_使用exec结合tail命令实现实时收集 143_使用seq源和压力源实现测试 144_使用avro源 145_导入avro maven-avro-client 146_导入avro maven-avro-client 147...