在任何数据类型作为同步锁时,需要注意的是,是否有多个线程同时持有锁对象,如果同时持有相同的对象,则这些线程之间就是同步的;如果分别获得锁对象,则这些线程之间就是异步。
package com.example.test;
public class Test193 {
private String lock ="laoqiang";
public static void main(String[] args) {
Test193 t = new Test193();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
t.testMethod();
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
t.testMethod();
}
});
t1.setName("t1");
t1.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t2.setName("t2");
t2.start();
}
public void testMethod() {
synchronized (lock) {
lock = "我换锁了";
System.out.println(Thread.currentThread().getName()+"开始执行任务");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"结束执行任务");
}
}
}
该程序运行结果就是异步,在第一个线程执行run方法的时候,实例属性已经改了,第二个线程得到的锁,和第一个不同。
上面演示是变量的值改变,如果对象作为锁,通过下面代码,你会发现只要对象不变,即使对象的熟悉被改变,运行结果还是同步的。
public class Test194 {
public static void main(String[] args) {
Test194 t = new Test194();
UserInfo ui1 = new UserInfo();
ui1.setAge(12);
ui1.setName("laoqiang");
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
t.show(ui1);
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
t.show(ui1);
}
});
t1.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t2.start();
}
public void show(UserInfo ui) {
synchronized (ui) {
System.out.println(Thread.currentThread().getName()+"开始");
ui.setAge(24);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"结束");
}
}
}