package day04;
/**
* 使用同步块来有效的减少同步范围,可以提高代码并发运行的效率。
*/
public class SyncDemo2 {
public static void main(String[] args) {
final Shop shop = new Shop();
Thread t1 = new Thread(){
public void run(){
try {
shop.buy();
} catch (Exception e) {}
}
};
Thread t2 = new Thread(){
public void run(){
try {
shop.buy();
} catch (Exception e) {}
}
};
t1.start();
t2.start();
}
}
class Shop{
/*
* 假设该方法需要同步(试衣服的过程)
*/
public void buy() throws InterruptedException{
//运行buy方法的线程
Thread t = Thread.currentThread();
System.out.println(t.getName()+":正在选衣服...");
Thread.sleep(5000);//假设甲/乙线程选衣服的过程是500毫秒。选衣服有很多衣服可以选,甲乙线程可以异步的执行。
synchronized(this){
System.out.println(t.getName()+":正在试衣服...");
Thread.sleep(5000);//假设甲/乙线程在试衣间试衣服的过程是500毫秒。试衣间只有1间试衣间可以试衣服,只有锁住这个公共资源
}
System.out.println(t.getName()+":结账离开");
}
}
程序运行结果:
Thread-1:正在选衣服...
Thread-0:正在选衣服...
Thread-0:正在试衣服...
Thread-1:正在试衣服...
Thread-0:结账离开
Thread-1:结账离开
还有可能是:
Thread-0:正在选衣服...
Thread-1:正在选衣服...
Thread-1:正在试衣服...
Thread-1:结账离开
Thread-0:正在试衣服...
Thread-0:结账离开
当一个类中的多个方法同时被synchronized修饰后,这些方法就是互斥的。
但是需要注意,静态方法与非静态方法之间没有互斥效果。原因在于他们锁的对象不同。非静态方法锁的是方法所属的对象,而静态方法锁的是类对象。
所以,有没有同步效果或互斥效果,关键在于不同线程看到的是否为相同的上锁对象。
下面的例子中Foo类有a()方法和b()方法。这连个方法都不是静态方法,所以t1线程和t2线程调用这两个方法时是互斥的。只能是一个线程执行完了之后,第2个线程在执行。
例2:
package day04;
/**
* 当一个类中的多个方法同时被synchronized修饰后,这些方法就是互斥的。
* 但是需要注意,静态方法与非静态方法之间没有互斥效果。原因在于他们锁的对象不同。非静态方法锁的是方法所属的对象,而静态方法锁的是类对象。
* 所以,有没有同步效果或互斥效果,关键在于不同线程看到的是否为相同的上锁对象。
* @author Administrator
*
*/
public class SyncDemo3 {
public static void main(String[] args) {
final Foo foo = new Foo();
Thread t1 = new Thread(){
public void run(){
foo.a();
}
};
Thread t2 = new Thread(){
public void run(){
foo.b();
}
};
t1.start();
t2.start();
}
}
class Foo{
public synchronized void a(){
Thread t = Thread.currentThread();
System.out.println(t.getName()+":调用a方法.");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println(t.getName()+":调用完a方法了.");
}
public synchronized void b(){
Thread t = Thread.currentThread();
System.out.println(t.getName()+":调用b方法.");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
System.out.println(t.getName()+":调用完b方法了.");
}
}
运行结果如下:
Thread-1:调用b方法.
Thread-1:调用完b方法了.
Thread-0:调用a方法.
Thread-0:调用完a方法了.