线程安全问题
多个线程执行的 不确定性, 引起执行结果的不稳定
多个线程, 对账本的共享, 会造成 操作的不完整性, 会破坏数据
创建3个窗口买票, 总票数为为100张, 使用实现Runnable接口的方式
1. 卖票过程中, 出现 重票, 错票, 出现了线程安全问题
问题出现的原因
当某个线程操作 车票 的过程中, 尚未操作完成时, 其他线程参与进来, 也操作车票
2. 解决方法
当一个线程a在操作 ticket 的时候, 其他线程不能参与进来
直到线程a 操作完 ticket时, 线程才可以开始操作 ticket, 这种情况即使 线程a 出现了阻塞, 也不能改变
在Java中, 通过 同步机制, 来解决的安全问题
2.1. 最初的方法
2.1.1. 同步代码块
synchronized(同步监视器) {
// 需要被同步的代码
}
什么叫 需要被同步的代码?
操作 共享数据的代码, 即为 需要被同步的代码
共享数据: 多个线程 共同操作 的变量, 比如 ticket 就是 共享数据
同步监视器, 俗称 锁,
任何一个类的对象, 都可以充当 锁
要求: 多个线程 必须要共用 同一把锁 (不能一个人, 一个锁)
class Windows1 implements Runnable{
private int ticket = 100;
Object obj = new Object();
@Override
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;
}
}
}
}
}
class WindowsTest1 {
public static void main(String[] args) {
Windows1 w = new Windows1();
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();
}
}
2.1.2. 同步方法
class Window2 extends Thread {
private static int ticket = 100;
// private static Object obj = new Object();
@Override
public void run() {
while (true) {
synchronized (Window2.class) {
if (ticket > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + ": 卖票, 票号为: " + ticket);
ticket--;
} else {
break;
}
}
}
}
}
public class WindowTest2 {
public static void main(String[] args) {
Window2 t1 = new Window2();
Window2 t2 = new Window2();
Window2 t3 = new Window2();
t1.setName("窗口1");
t2.setName("窗口2");
t3.setName("窗口3");
t1.start();
t2.start();
t3.start();
}
}
3. jdk5新增的解决方法
参考链接