在同一个时间点,N个线程访问同一个资源,会引发线程不安全问题!
解决办法:
同步代码块和同步代码方法 synchronized 给线程上锁。
同步和异步的定义:
同步(synchronous):也称阻塞。一个线程再去执行一个操作时,如果这个操作有一个值需要返回,那么所有线程需要等待这个操作结束,返回值得到以后才可以继续执行线程的抢占资源。
异步(asynchronous):与同步不同的是,当一个线程的操作需要返回值是,其他线程不需要等待,可以去做其他的事情。
注意点:
01.在同一个时间点,只有一个线程能进入synchronized修饰的方法或者代码块
02.当一个线程访问synchronized代码块或者方法的时候,其他线程等待,其他synchronized代码块也会被锁定!
03.当一个线程访问synchronized代码块或者方法的时候,其他的线程可以访问非synchronized修饰的代码块或者方法!
1 /** 2 * 售票的线程类 考虑并发 使用同步代码块 3 */ 4 public class SaleThreadBlock implements Runnable { 5 // 定义总票数 6 private int counts = 100; 7 // 定义出售的票数 8 private int num = 0; 9 10 @Override 11 public void run() { 12 while (true) { 13 /** 14 * 在多个线程并发访问run() 15 * 只有一个线程能进入synchronized同步代码块, 16 * 只有当这个线程执行完毕,出来之后,其他线程才能进入 17 */ 18 synchronized (this) { 19 if (counts <= 0) { 20 break; // 没有票 退出 循环 21 } 22 // 售票 23 counts--; 24 num++; // 记录出售的票数 25 System.out.println(Thread.currentThread().getName() + "抢到了第" 26 + num + "张票,剩余票数:" + counts); 27 } 28 } 29 30 } 31 32 // 测试方法 33 public static void main(String[] args) { 34 SaleThreadBlock block = new SaleThreadBlock(); 35 // 创建线程对象 36 Thread t1 = new Thread(block, "张三"); 37 Thread t2 = new Thread(block, "李四"); 38 Thread t3 = new Thread(block, "王五"); 39 Thread t4 = new Thread(block, "老黄牛"); 40 System.out.println("============所有人 开始抢票============"); 41 // 启动线程 42 t1.start(); 43 t2.start(); 44 t3.start(); 45 t4.start(); 46 47 } 48 }
1 /** 2 * 售票的线程类 考虑并发 使用同步代码方法 3 */ 4 public class SaleThreadMethod implements Runnable { 5 // 定义总票数 6 private int counts = 100; 7 // 定义出售的票数 8 private int num = 0; 9 10 // 定义一个标记 票是否出售完毕 11 boolean flag = false; 12 13 @Override 14 public void run() { 15 while (!flag) { 16 sale(); // 只要还有票 就一直出售 17 } 18 19 } 20 21 /** 22 * 在多个线程并发访问run() 23 * 只有一个线程能进入synchronized同步代码方法, 24 * 只有当这个线程执行完毕,出来之后,其他线程才能进入 25 */ 26 public synchronized void sale() { 27 if (counts <= 0) { 28 flag = true; 29 return; // 没有票 退出 循环 30 } 31 // 售票 32 counts--; 33 num++; // 记录出售的票数 34 System.out.println(Thread.currentThread().getName() + "抢到了第" + num 35 + "张票,剩余票数:" + counts); 36 } 37 38 // 测试方法 39 public static void main(String[] args) { 40 SaleThreadMethod block = new SaleThreadMethod(); 41 // 创建线程对象 42 Thread t1 = new Thread(block, "张三"); 43 Thread t2 = new Thread(block, "李四"); 44 Thread t3 = new Thread(block, "王五"); 45 Thread t4 = new Thread(block, "老黄牛"); 46 System.out.println("============所有人 开始抢票============"); 47 // 启动线程 48 t1.start(); 49 t2.start(); 50 t3.start(); 51 t4.start(); 52 53 } 54 }