线程安全问题及解决方法
(1)多线程安全问题的原因(也是我们判断一个程序是否有线程安全问题的依据)
A:是否有多线程环境
B:是否有共享数据
C:是否有多条语句操作共享数据
(2)如何解决多线程安全问题呢?
基本思想:让程序没有安全问题的环境。
怎么实现呢?
把多个语句操作共享数据的代码给锁起来,让任意时刻只能有一个线程执行即可(同步代码块)
(10)同步解决线程安全问题
A:同步代码块
synchronized(对象){
需要同步的代码;
}
a:对象是什么呢?
可是是任意对象。
b:需要同步的代码是哪些呢?
把多条语句操作共享数据的代码的部分给包起来
注意:
同步可以解决安全问题的根本原因就在那个对象上。该对象如同锁的功能。
多个线程必须是同一把锁。
Eg:代码:
public class SellTicket implements Runnable { // 定义100张票 PRivate int tickets = 100; //创建锁对象 private Object obj = new Object();//也可以是任意对象 @Override public void run() { while (true) { synchronized (obj) { //不可以在这里new一个对象,因为我们要是同一把锁 if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票"); } } } } }B:同步方法
把同步加在方法上。
这里的锁对象是this//(默认的)
Eg:代码
private synchronized void sellTicket() { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 "); } }C:静态同步方法
把同步加在方法上。
这里的锁对象是当前类的字节码文件对象(反射再讲字节码文件对象)//(默认SellTicket.class)
Eg:代码:
private static synchronized void sellTicket() { if (tickets > 0) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "张票 "); } }
D:同步的特点
1、同步的前提
多个线程
多个线程使用的是同一个锁对象
2、同步的好处
同步的出现解决了多线程的安全问题。
3、同步的弊端
当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的运行效率。