四 Synchronized
首先,一个问题:一个boolean成员变量,一个方法赋值,一个方法读值,多线程环境下,需要同步吗?
如果用同步的话,读也要用synchroized修饰,因为可见性的问题
需要同步,或者用volatile。boolean赋值和读值是原子的,但是依旧有可见性问题,否则也许读方法永远都不到最新的值。
Synchronized的用法:
1:修饰代码块:
修饰的是当前的对象。
synchronized(this){
}
synchronized锁住的是代码还是对象? 答案是:synchronized锁住的是括号里的对象,而不是代码。
本方法与2相比,粒度可以更小,性能更优越一些。
当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的对象来充当锁:
class Test implements Runnable
{
private byte[] lock = new byte[0]; // 特殊的instance变量
public void method()
{
synchronized(lock)
{ // todo 同步代码块 }
}
public void run()
{ }
}
注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。
2:修饰非静态方法:
public synchronized void test() {
}
对于非static的synchronized方法,锁的就是对象本身也就是this。
注意:当一个线程访问对象的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该对象中的非synchronized(this)同步代码块
synchronized关键字不能继承
3:修饰静态方法:
同步的是整个类以及所有对象
4:修饰一个类:
class ClassName
{ public void method()
{ synchronized(ClassName.class)
{ // todo }
}
}