线程在执行的过程中,容易出现安全问题,除了 外,所谓的安全问题就是:
对需要同步的变量进行多线程操作时,会使变量的判定发生问题,比如卖票的问题可能出现0票或者-1,-2的情况,
那么我们就需要一个锁来对需要同步的变量或者方法进行标记,指示:
该变量或方法在某个时刻或时间段只能被一个线程所执行
1 //错误代码演示: 2 public class ThreadDemo implements Runnable { 3 //创建线程的第一种方式:继承Thread类 4 private int ticket =100; 5 Object object = new Object(); 6 @Override 7 public void run() { 8 while(true) { 9 if (ticket>0) {10 try {11 Thread.sleep(10);12 } catch (Exception e) {}13 System.out.println(Thread.currentThread().getName()+"-----"+ticket--);14 }15 }16 }17 }18 19 //正确代码演示:20 public class ThreadDemo implements Runnable {21 //创建线程的第一种方式:继承Thread类22 private int ticket =100;23 Object object = new Object();24 @Override25 public void run() {26 while(true) {27 synchronized (object) {28 if (ticket>0) {29 try {30 Thread.sleep(10);31 } catch (Exception e) {32 }33 System.out.println(Thread.currentThread().getName()+"-----"+ticket--);34 }35 }36 }37 }38 }
线程所使用的锁是有不同的,
在普通的方法或者同步代码块中:
当方法是非静态的,锁指的是调用这个方法的对象本身,也就是this;
当方法是静态的,锁指的是该方法所在类的字节码对象,也就是类名.class
演示同步代码块和同步函数的使用方法:
1 //同步代码块的使用: 2 public void run() { 3 while(true) { 4 //锁this指的是调用本方法的类实例对象 5 synchronized (this) { 6 if (ticket>0) { 7 try { 8 Thread.sleep(10); 9 //线程休眠是为了看清同步的效果,有没有产生错误的票号10 } catch (Exception e) {11 }12 System.out.println(Thread.currentThread().getName()+"-----"+ticket--);13 }14 }15 }16 }
1 //同步函数的使用: 2 public class ThreadDemo implements Runnable { 3 private int ticket =100; 4 @Override 5 public void run() { 6 while(true) { 7 synchMethod(); 8 } 9 }10 public synchronized void synchMethod() {11 if (ticket>0) {12 try {13 Thread.sleep(10);14 //线程休眠是为了看清同步的效果,有没有产生错误的票号15 } catch (Exception e) {16 }17 System.out.println(Thread.currentThread().getName()+"-----"+ticket--);18 }19 }20 }21 22 //当同步的方法是静态的时候,锁使用的是本类的字节码对象:类名.class23 public class ThreadDemo implements Runnable {24 //这时候静态方法使用的变量也要是静态的25 private static int ticket =100;26 @Override27 public void run() {28 while(true) {29 synchMethod();30 }31 }32 public static synchronized void synchMethod() {33 if (ticket>0) {34 try {35 Thread.sleep(10);36 //线程休眠是为了看清同步的效果,有没有产生错误的票号37 } catch (Exception e) {38 }39 System.out.println(Thread.currentThread().getName()+"-----"+ticket--);40 }41 }42 }