多线程-同步代码块(同步的好处和弊端以及同步的前提条件)
1 package multithread.test; 2 3 import com.sun.org.apache.bcel.internal.generic.NEW; 4 5 /* 6 * 卖票 7 */ 8 9 10 /* 11 * 线程安全问题产生的原因: 12 * 1,多个线程在操作共享的数据。 13 * 2,操作共享数据的线程代码有多条。 14 * 15 * 当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算。 16 * 就会导致线程安全问题的产生。 17 * 18 * 19 * 解决思路: 20 * 就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候 21 * 其他线程是不可以参与运算的。 22 * 必须要当前线程把这些代码都执行完毕后,其他线程才可以参与运算。 23 * 24 * 25 * 在java中,用同步代码块就可以解决这个问题。 26 * 27 * 同步代码块的格式: 28 * synchronize(对象){ 29 * 需要被同步的代码块 30 * } 31 * 同步代码块的好处:解决了线程的安全问题。 32 * 33 * 34 * 同步的弊端:相对降低了效率,因为同步外的线程的都会判断同步锁。 35 * 36 * 同步的前提:必须有多个线程并使用同一个锁。 37 * 38 * 39 * 40 */ 41 42 43 class Ticket implements Runnable {//extends Thread { 44 private /*static*/ int num = 100;//静态是可以的,根据实际看,有可能是这个线程负责这种100张,另一个线程时另一种票100张 45 Object obj = new Object(); 46 public void run() /*throws 不处理就抛,但是实现接口覆盖的方法,接口没有声明过异常,只能catch不能声明*/{ 47 // Object obj = new Object();//每个线程开启都会创建一个对象,就会有不同锁,会出错 48 while(true) { 49 synchronized (obj/*对象锁或者叫同步锁*/){ 50 if (num>0) { 51 // try { 52 // Thread.sleep(10);//sleep方法有个抛出 53 // } catch (InterruptedException e) { 54 // // TODO: handle exception 55 // } 56 // // 57 System.out.println(Thread.currentThread().getName()+"....sale...."+ num--); 58 } 59 } 60 61 62 } 63 } 64 } 65 66 public class TicketDemo { 67 68 public static void main(String[] args) { 69 // TODO Auto-generated method stub 70 71 Ticket t = new Ticket();//创建一个线程任务对象。 72 73 74 Thread t1 = new Thread(t); 75 Thread t2 = new Thread(t); 76 Thread t3 = new Thread(t); 77 Thread t4 = new Thread(t); 78 79 t1.start(); 80 t2.start(); 81 t3.start(); 82 t4.start(); 83 /* 84 Ticket t1 = new Ticket(); 85 Ticket t2 = new Ticket(); 86 Ticket t3 = new Ticket(); 87 Ticket t4 = new Ticket(); 88 //只有100张,卖了400张,为什么? 89 t1.start(); 90 // t1.start();IllegalThreadStateException-无效线程状态异常是 runtime异常 91 // t1.start(); 92 // t1.start(); 93 94 t2.start(); 95 t3.start(); 96 t4.start(); 97 */ 98 99 100 } 101 //cmd 打印完1在前面 比如43打印在后面, cmd是应用程序,虚拟机也是一个应用程序,cpu也是在这两个中切换造成的 102 }