Java中synchronized的使用方法

Java中synchronized的使用方法,第1张

Java中synchronized的使用方法,第2张

synchronized[/Br/]public class text thread[/Br/]{[/Br/]/* *[/Br/]* @ paramargs[/Br/]*/[/Br/]public static void main(string[]args)[/Br/]{[/Br/]/Todo自动生成方法存根[/Br/]TxtThread TT = new TxtThread();
新线程(tt)。start();
新线程(tt)。start();
新线程(tt)。start();
新线程(tt)。start();
}
}
类TxtThread实现Runnable
{
int num = 100;
String str = new String();
public void run()
{
while(true)
{
synchronized(str)
{
if(num > 0)
{
try
{
thread . sleep(10);
}
catch(异常e)
{
e . getmessage();
}
system . out . println(thread . current thread()。getName()+"这是"+num-);
}
}
}
}
]在上面的例子中,为了制造一个时间差,也就是出错的几率,Thread.sleep(10)
Java对多线程的支持和同步机制深受影响。最近怎么样?――你得对同步关键词的作用有深入的了解,才能下结论。
一般来说,synchronized关键字可以作为函数的修饰符,也可以作为函数内的语句,即同步方法和同步语句块。如果你详细分类,synchronized可以用在实例变量、对象引用、静态函数和类文字上。
在进一步阐述之前,我们需要明确几点:
a .无论synchronized关键字是添加到方法还是对象,它获取的锁都是对象,而不是用一段代码或函数作为锁――而且synchronized方法也可能被其他线程的对象访问。
B .每个对象只有一个关联的锁。
C .实现同步需要耗费大量的系统开销,甚至可能造成死锁,所以尽量避免不必要的同步控制。
接下来我们讨论一下异地同步使用对代码的影响:
假设P1和P2是同一个类的不同对象,在这个类中定义了以下同步块或方法,P1和P2都可以调用它们。
1。synchronizing用作函数修饰符时,示例代码如下:
public synchronized void method AAA()
{
/…
}
这是同步方法,然后synchronized。它锁定调用此同步方法的对象。也就是说,当一个对象P1在不同的线程中执行这种同步方法时,它们会互相排斥,达到同步的效果。但是,由该对象所属的类生成的另一个对象P2可以使用synchronized关键字任意调用该方法。
上面的示例代码等效于下面的代码:
public void method AAA()
{
synchronized(this)//(1)
{
/...
它是指调用此方法的对象,如P1。可见,同步方法的本质是将synchronized应用于对象引用。――只有获得P1对象锁的线程才能调用P1的同步方法。对于P2来说,P1的锁与之无关,程序在这种情况下可能会摆脱同步机制的控制,导致数据混乱。2.同步块,代码如下:
public void方法3(某对象so)
{
synchronized(so)
{
/...
} [/br]当有一个显式对象作为锁时,可以这样写程序,但是当没有显式对象作为锁,而只是想同步一段代码时,可以创建一个特殊的实例变量(必须是对象)来充当锁:
classfoo实现runnable
{
private byte[]lock = new byte。//特殊实例变量
public void method()
{
synchronized(lock){//…}
}
/...
}
注意:零长度字节数组对象创建起来会比任何对象都经济――查看编译后的字节码:生成零长度字节[]对象只需要3个操作码,而Object lock = new Object()需要7个操作码。
3。将synchronized应用于静态函数,代码如下:
class foo
{
public synchronized static void method AAA()//synchronized static function
{
/…。
}
Void method BBB()
{
synchronized(foo . Class)//Class literal(类名的文字常量)
}
} MethodBBB()在
代码中,方法使用类文字作为锁,与同步静态函数具有相同的效果。得到的锁很特殊,是调用这个方法的对象当前所属的类(类,而不是这个类生成的特定对象)。
我记得《有效的Java》这本书里那个Foo。Class和P1.getClass()在用作同步锁时是不同的。P1.getClass()不能用于锁定该类。P1指的是Foo类生成的对象。
可以推断,如果一个同步的静态函数A和一个同步的实例函数B定义在一个类中,那么这个类的同一个对象obj在多线程中访问这两个方法A和B时不会同步,因为它们的锁是不同的。方法A的锁是对象obj,方法B的锁是Obj所属的类。
总结如下:
知道synchronized锁定了哪个对象,可以帮助我们设计出更安全的多线程程序。
有一些技巧可以让我们对共享资源的同步访问更加安全:
1。定义私有实例变量+它的get方法,而不是公共/受保护的实例变量。如果变量被定义为public,那么对象可以绕过同步方法的控制,直接获取并更改它。这也是JavaBean的标准实现之一。
2。如果实例变量是一个对象,比如数组或者ArrayList什么的,那么上面的方法还是不安全的,因为当一个外部对象通过get方法获取这个实例对象的引用,并指向另一个对象时,私有变量也会发生变化。不是很危险吗?这时就需要用synchronized同步get方法,只返回这个私有对象的clone()——这样,调用者就会得到对象副本的引用。

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » Java中synchronized的使用方法

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情