解决线程安全问题
方式一:同步代码块
1,Runnable接口的优化
没解决线程同步问题时,if中写入Thread.sleep(100);可以增加错票几率
synchronized(同步监视器){
需要被同步的代码
}
说明:
- 操作共享数据的代码就是需要被同步的代码
- 共享数据:多个线程共同操作的变量。比如: ticket就是共享数据。
- 同步监视器,俗称:锁。任何一个类的对象,都可以充当锁。
- 要求:多个线程必须要共用同一把锁。
class Window1 implements Runnable{
private int ticket = 100;
//随便new一个充当锁
Object obj = new Object();
public void run(){
while(true){
//同步监视器
synchronized (obj) {
if (ticket > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket);
ticket--;
} else {
break;
}
}
}
}
}
public class WindowTest1 {
public static void main(String[] args) {
Window1 w = new Window1();
Thread t1 =new Thread(w);
Thread t2 =new Thread(w);
Thread t3 =new Thread(w);
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
结果无错票:三个线程共用一个window1对象,window1对象中只有一个obj,因此三个线程共用一把锁。
假设将Object obj = new Object();放入run()方法中,就不成立了,因为不满足共用一把锁。
说明:这个代码中可以写为:ynchronization(this)因为this是调用这个方法的对象,而对象自始至终只有一个,因此没问题
局限性:操作同步代码时,只能有一个线程参与,其他线程等待。相当于是一个单线程的过程,效率低。
2,继承Thread方式的优化
没解决线程同步问题时,if中写入Thread.sleep(100);可以增加错票几率
运行结果:
加synchronization后依然有重票
class Window2 extends