就拿毕老师同步买票那个例子来说: 如果你用同步函数的话:
lass Ticket implements Runnable{
private int num=100;
public void run(){
show();
}
public synchronized void show() {
while (true) {
if (num == 0) return;
try {Thread.sleep(30);} catch (InterruptedException e) {}
System.out.println("...." + Thread.currentThread().getName()+ "....." + num--);
}
}
}
public class TicketSell {
public static void main(String[] args) {
Ticket t=new Ticket();
Thread t1=new Thread(t);
Thread t2=new Thread(t);
Thread t3=new Thread(t);
Thread t4=new Thread(t);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
这样子看起来是对的,但你编译后会知道这里只有一个线程在使用,另一个线程时抢不到的。这是因为一个线程进去同步函数,把循环做完才算同步。所以要求你将可能并发出syn{},写起来比同步函数稍微难写点.
class Ticket1 implements Runnable{
private int num = 100;
Object obj = new Object();
public void run(){
while(true){
synchronized(obj){
if(num==0) return;
try{Thread.sleep(30);}catch (InterruptedException e){}
System.out.println(Thread.currentThread().getName()+".....sale...."+num--);
}
}
}
}
//主函数省略了
这样写就会清晰的明白那里加同步。
还有就是要注意的是:
1.同步代码块,使用的锁可以是任意对象,但是操作共享资源时,锁必须唯一!
2.同步函数,使用的锁是this!
而且同步代码块又是可以用双重否定来解决效率低的问题
比如懒汉式:
class Single{
private static Single s = null;
private Single(){}
public static Single getInstanc(){
if(s==null){
synchronized (Single.class) {
if(s==null)
s = new Single();
}
}
return s;
}
} |