java 并发编程 synchronized

[align=center][size=medium][color=darkred][b]同步原语--synchronized
[/b][/color][/size][/align]
synchronized(class)很特别,它会让另一个线程在任何需要获取class做为monitor的地方等待.class与this做为不同的监视器可以同时使用,不存在一个线程获取了class,另一个线程就不能获取该class的一切实例.


[list]
[*] [b][color=green]->线程各自获取monitor,不会有等待.[/color][/b]
synchronized(class)
synchronized(this)


[*] [b][color=green]->如果不同线程监视同一个实例对象,就会等待,如果不同的实例,不会等待.[/color][/b]
synchronized(this)
synchronized(this)


[*] [b][color=green]->如果不同线程监视同一个实例或者不同的实例对象,都会等待.[/color][/b]
synchronized(class)
synchronized(class)

[/list]

===============================================================================

[color=darkred][b]接着来讨论synchronized用到不同地方对代码产生的影响:[/b][/color]

假设P1、P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1、P2就都可以调用它们。

[b]1. 把synchronized当作函数修饰符时,示例代码如下:[/b]

Public synchronized void methodAAA()

{

//….

}


[color=green]这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了[/color]

[b]synchronized关键字的方法。[/b]

上边的示例代码等同于如下代码:

public void methodAAA()

{

synchronized (this) // (1)

{

//…..

}

}


[color=green](1)处的this指的是什么呢?它指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于object reference。――那个拿到了P1对象锁的线程,才可以调用P1的同步方法,而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造成数据混乱:([/color]

[b]2.同步块,示例代码如下:[/b]

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) { //… }

}

//…..

}


[color=green]注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。[/color]

[b]3.将synchronized作用于static 函数,示例代码如下:[/b]

Class Foo 
{

public synchronized static void methodAAA() // 同步的static 函数
{
//….
}

public void methodBBB()
{

synchronized(Foo.class) // class literal(类名称字面常量)

}
}


[color=green]代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。[/color]

记得在《Effective Java》一书中看到过将 Foo.class和 P1.getClass()用于作同步锁还不一样,不能用P1.getClass()来达到锁这个Class的目的。P1指的是由Foo类产生的对象。
[/list]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值