通过一个卖票问题,验证多线程中同步代码块与同步函数的锁。
卖票系统,两台机器t1线程和t2线程,共同卖掉100张票。
package day13;
public class SynFunctionLockDemo {
public static void main (String[] args){
Ticket t =new Ticket();//一个对象,共享100张票
System.out.println("t :"+t);
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
try{Thread.sleep(10);}catch(InterruptedException e){}
t.flag = false;
t2.start();
/*解释第九行 这一步,
*在主进程main中,t1.start和t2.start以及t.flag=false同时运行到了
*主线程进行了flag->false的过程
*t1和t2线程都只能在flag=false的同步函数中进行
*/
}
}
class Ticket implements Runnable{
private int num = 100;
boolean flag =true;
Object obj = new Object();
public void run(){
System.out.println("this:"+this);
if(flag){//同步代码块
for(int i=200;i>1;i--){
synchronized(obj){
if(num>0){
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"...obj..."+num--);
}
}
}
}
else{
for(int i=200;i>1;i--)
show();
}
}
public synchronized void show(){//同步函数
if(num>0){
try{Thread.sleep(10);}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+"...function.."+num--);
}
}
}
运行之后,结果会出现第0号票的可能,出现错误,说明同步函数和同步代码块的锁是不相同的。
如果将28行的synchronized(obj)改成synchronized(this)
结果不会出现第0号票,正确,这种改法保证了同步代码块和同步函数锁的一致性,同时也验证同步代码块与同步函数的锁是不一样的。
同步函数的使用的锁是this:
同步函数和同步代码块的区别:
同步函数的锁是固定的this。
同步代码块的锁是任意的对象。
建议使用同步代码块。