public class Person {
private String name;
private static final String TAG = Person.class.getSimpleName();
public Person(String name) {
this.name = name;
}
// Synchronized修饰一个方法
public synchronized void say(){
for(int i = 0; i < 10; i++){
try {
Log.d(TAG, name + " say -> " + i)
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Synchronized修饰一个代码块
// 如果像这样代码块是函数内的全部代码,那同步效果与上面修饰方法是一样的
public void say(){
synchronized(this) {
for(int i = 0; i < 10; i++){
try {
Log.d(TAG, name + " say -> " + i)
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void talk(){
for(int i=0;i<3;i++){
try {
Log.d(TAG, name + " talk -> " + i)
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
这个属于对象锁,synchronized锁定的是对象(实例?),这时会有两把锁分别锁定 对象1 和 对象2,而这两把锁是互不干扰的,不形成互斥,所以两个线程可以同时执行。
Person person1 = new Person();
Person person2 = new Person();
如果两个线程同时分别对两个对象进行操作,两个对象的函数 say 或者 talk 是不会锁定的,互补干扰。
但是如果这么写
public void say(){
synchronized(Person.class) {
for(int i = 0; i < 10; i++){
try {
Log.d(TAG, name + " say -> " + i)
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
这样的话,锁定的范围就扩大到 类了,属于类锁,不再局限为对象。
所有这个类的实例,都会存在同步的效果
Tips
当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的对象来充当锁:
private byte[] lock = new byte[0]; // 特殊的常量,为什么用byte[]
public void method()
{
synchronized(lock) {
// Todo 同步代码块
}
}
零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。