多线程拜访了共享的数据,会产生线程平安问题
public class RunnalbeImpl implements Runnable{ //定义一个多个线程共享的票源 private int ticket = 100; //设置线程工作:买票 @Override public void run() { while (true) { //判断票是否存在 if (ticket > 0) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "买第" + ticket + "张票"); ticket--; } } }}
public class Demo04Ticket { public static void main(String[] args) { /* 创立三个线程,同时开启,对共享的票进行发售 同一个实现类,多个线程,才会共享 */ //创立Runnable接口的实现类对象 RunnalbeImpl run = new RunnalbeImpl(); //创立Thread类对象,传递上述实现类对象 Thread t0 = new Thread(run); Thread t1 = new Thread(run); Thread t2 = new Thread(run); t0.start(); t1.start(); t2.start(); }}
线程平安问题产生的原理
sleep使得线程放弃对CPU的执行权
t0, t1, t2同时执行到了一个程序代码(代码执行有工夫,所以变动值的语句还没来得及执行,上一句就被屡次执行)
线程平安问题是不能产生的,因而能够让一个线程在访问共享数据的时候,无论是否失去了CPU的执行权,其余的线程只能期待。
(保障始终一个线程在工作)
解决:
1.同步代码块
格局:
synchronized(同步锁) { //同步代码块 //可能会呈现线程平安的代码(拜访了共享数据的代码)}
留神:
- 通过代码块的锁对象,能够应用任意的对象
- 保障多个线程应用同一个锁对象
- 作用是:把同步代码块锁住,只让一个线程在同步代码块中执行
public class RunnalbeImpl implements Runnable{ //定义一个多个线程共享的票源 private int ticket = 100; //创立一个锁对象,然而不能放run中,那样会产生多个锁对象 Object obj = new Object(); //设置线程工作:买票 @Override public void run() { while (true) { synchronized (obj) { //判断票是否存在 if (ticket > 0) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "买第" + ticket + "张票"); ticket--; } } } }}
同步技术的原理
同步中的线程,没有执行结束不会开释锁
同步外的线程,没有锁进不去同步
程序频繁的判断锁、获取锁、开释锁,程序的效率升高,进步安全性