问题分析:出现了数据安全问题 , 主要原因就是同一时间有多个线程操作了共享的数据
我们这个程序一开始会出现多个窗口卖出了同一张票
这种情况就是出现了数据安全的问题
出现数据安全的问题的原因
1.是否有多线程环境
2.是否有共享数据 这里的共享数据就是 tickets
3.是否有多条语句操作共享数据 这里就是对数据的输出 和++ 操作
解方法就是给程序加锁,在某一段时间只能有一个程序操作共享数据破坏第三个条件
具体代码的分析:
private int tickets = 1;
public void run() {
//现在窗口一 窗口二 窗口三 都跑到这里了
//现在tickets = 1
//假设窗口一抢占到了资源
while (true){
if(tickets <= 200){ //100z张票
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
//窗口一 线程到这里了 已经卖出了第一章票 但是现在tickets = 1
突然cpu资源被线程二抢走了 此时 tickets = 1 还没进行 ++
所以线程二就又卖出了第二张票
//但是我不明白为什么有时候已经卖出了第58还是会出现
又卖出了 第一张票这么神奇的事情 ticket都已经变为58 怎么又会变为一
难道是因为我的电脑太垃圾了线程卡了??
tickets++;
}
}
}
*/
使用同步代码块解决数据安全问题
解决多个窗口同时卖出同一张票
卖票的类
public class SaleTickets implements Runnable {
private int tickets = 1;
private Object obj =new Object() ;
@Override
public void run() {
//窗口一直等着别人来买票
while (true){
//synchronized (new Object()){
//这样写是错误的 ,因为每一个线程走到这里都会new 一个object对象 就是new出来三把锁
//这样是不行的 要使用一个线程来锁住按个线程 所以要把 new Object 放在外面
synchronized (obj){
if (tickets <= 100){
System.out.println(Thread.currentThread().getName()+"卖出了第:"+tickets+"张票");
//票数加一
tickets++;
//卖票员休息一下
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
测试类
public class Test {
/*
我们这个程序一开始会出现多个窗口卖出了同一张票
这种情况就是出现了数据安全的问题
出现数据安全的问题的原因
1.是否有多线程环境
2.是否有共享数据 这里的共享数据就是 tickets
3.是否有多条语句操作共享数据 这里就是对数据的输出 和++ 操作
if (tickets <= 100){
System.out.println(Thread.currentThread().getName()+"卖出了第:"+tickets+"张票");
//票数加一
tickets++;
}
//怎么解决这种情况
吧多条语句操作共享数据的代码用一把锁给锁起来 让任意时刻只有一个线程执行即可
可以使用同步代码块实现 格式:
synchronized(任意对象){
多条语句操作共享数据的代码
}
//我们分析一下同步代码快的运行 流程
while (true){
//tickets = 100 ;
//t1,t2,t3 都进来了
//假设t1抢占到了资源
synchronized (obj){
if (tickets <= 100){
System.out.println(Thread.currentThread().getName()+"卖出了第:"+tickets+"张票");
//票数加一
tickets++;
//卖票员休息一下
try {
Thread.sleep(100);
//t1到这里休息了 假如此时t2抢占到了资源 但是此时锁还在锁着 t2进不来的
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//到这里t1出来了 锁就解开了 t2就可以进去了
*/
public static void main(String[] args) {
//创建线程资源对象
SaleTickets saleTickets = new SaleTickets();
//创建线程对象
Thread thread1= new Thread(saleTickets,"窗口一");
Thread thread2= new Thread(saleTickets,"窗口二");
Thread thread3= new Thread(saleTickets,"窗口三");
//开始线程
thread1.start();
thread2.start();
thread3.start();
//输出之后确实发现了有几个线程输出了同一个对象
// 怎么解决这这问题??? 使用锁那
}
}