public class test{ public static void main(String[] args) throws IOException{ Thread1 t1 = new Thread1("A"); Thread1 t2 = new Thread1("B"); Thread1 t3 = new Thread1("C"); t1.start(); t2.start(); t3.start(); } }
class Thread1 extends Thread{ private static int num = 50; public Thread1(String string){ super(string); } @Override public void run(){ for(int i=0;i<50;i++){ try { sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if(num>0){ System.out.println(this.currentThread().getName()+">>>>>"+(--num)); } } } }
C>>>>>48 A>>>>>48//出现重复数字 B>>>>>49 A>>>>>47 B>>>>>47 C>>>>>46 B>>>>>45 C>>>>>44 A>>>>>45 B>>>>>42 C>>>>>42 A>>>>>43 C>>>>>41 B>>>>>41 A>>>>>41 B>>>>>40 C>>>>>40 A>>>>>40 B>>>>>39 A>>>>>39 C>>>>>39 A>>>>>38 B>>>>>38 C>>>>>38 C>>>>>37 B>>>>>36 A>>>>>37 A>>>>>35 C>>>>>33 B>>>>>34 C>>>>>32 A>>>>>31 B>>>>>30 C>>>>>29 A>>>>>29 B>>>>>29 A>>>>>28 C>>>>>28 B>>>>>27 C>>>>>26 A>>>>>26 B>>>>>26 A>>>>>25 C>>>>>24 B>>>>>25 B>>>>>23 C>>>>>22 A>>>>>23 C>>>>>21 A>>>>>21 B>>>>>20 C>>>>>19 A>>>>>19 B>>>>>19 B>>>>>18 A>>>>>17 C>>>>>16 C>>>>>15 B>>>>>13 A>>>>>14 C>>>>>12 A>>>>>11 B>>>>>12 A>>>>>10 C>>>>>10 B>>>>>10 A>>>>>9 C>>>>>8 B>>>>>8 B>>>>>7 A>>>>>5 C>>>>>6 A>>>>>4 B>>>>>4 C>>>>>4 B>>>>>2 C>>>>>1 A>>>>>3 A>>>>>0 C>>>>>-1//出现负数 B>>>>>0
原因:当两个线程同时进入到if(num>0)的代码块中,一个线程开始执行输出语句,但还没执行到--num,另一条线程也开始执行打印操作,就会打印相同的数字。同样,当一条线程执行完--num且num=0,就会出现另一条线程执行完--num出现的是-1。
解决办法:
- 使用同步代码块
public void run(){ for(int i=0;i<50;i++){ //使用同步代码块 synchronized(this.getClass()){ if(num>0){ ··· } } } }
语法:
synchronized(同步锁){ //需要同步操作的代码(最多只有一个线程能够拿到同步锁,拿到同步锁之后该线程才能进入代码块) }
- 使用同步方法
使用synchronized关键字来修饰方法
@Override public void run(){ for(int i=0;i<50;i++){ sell(); } } private synchronized void sell(){ if(num>0){ ··· } }
注意:不能用synchronized来修饰run()方法,不然只能有一个线程进去执行完所有的操作。
- 使用锁机制
public class test{ public static void main(String[] args) throws IOException{ Lock l = new ReentrantLock(); Thread1 t1 = new Thread1("A",l); Thread1 t2 = new Thread1("B",l); Thread1 t3 = new Thread1("C",l); t1.start(); t2.start(); t3.start(); } } class Thread1 extends Thread{ String name; Lock lock; private static int num = 50; public Thread1(String string,Lock lock) { this.name = string; this.lock = lock; } @Override public void run(){ for(int i=0;i<50;i++){ lock.lock(); try { if(num>0){ sleep(10); System.out.println(this.currentThread().getName()+">>>>>"+(--num)); } } catch (InterruptedException e) { e.printStackTrace(); } finally{ lock.unlock(); } } } }注意:要把锁作为参数给每一个线程。