我们先来写一个买票程序
我们先创建一个包 在包下创建两个类
customException 线程类 负责编写抢票的主要逻辑
参考代码如下
public class customException implements Runnable {
private int tickets = 100;
public void run () {
while (tickets > 0){
if(tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}
}
text 测试类 用于实例化线程对象 并执行线程
public class text {
public static void main(String args[]) {
Runnable Runnable = new customException();
Thread m1 = new Thread(Runnable,"客户");
Thread m2 = new Thread(Runnable,"黄牛");
Thread m3 = new Thread(Runnable,"导爷");
m1.start();
m2.start();
m3.start();
}
}
然后 我们运行代码

我们会发现 第一百张票被抢了三次

负一也出来啦 这就是我们要解决的问题 线程执行随机性导致同一张票出售多次
科普个知识
java有特意为此现象 定义了数据安全性的描述

那么 显然 我们不是一个单线程 而是多线程 第一条 我们是到达了不安全的条件的
我们有一个tickets共享数据 所以 第二个条件 我们也是达到了不安全条件的
第三个 我们确实是在线程中 操作了 tickets 共享数据 tickets –
所以 这三个条件我们都达到了不安全的条件
java提供了 synchronized 锁方法解决这个问题 接受一个对象参数
这里 我们将customException 的 run方法修改代码如下
public void run () {
while (tickets > 0){
synchronized (new Object()) {
if(tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}
}
此时 我们调用了synchronized 将操作公共数据的代码锁了起来 运行结果如下

但很明显 问题并没有解决 因为我们传递对象是在方法中定义的 每个线程进来 看到的锁都是不一样的
那么 我们可以写一个公共的对象来锁
customException类代码修改如下
public class customException implements Runnable {
private int tickets = 100;
private Object obj = new Object();
public void run () {
while (true){
synchronized (obj) {
if(tickets > 0) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets+"张票");
tickets--;
}
}
}
}
}
这里我们直接定义了一个叫 obj 的公共对象 来定义同步锁
然后我们执行代码


可以看到 我们的数据已经是正常的执行了 这就解决了我们上述的问题
这篇博客通过一个简单的抢票程序,展示了在多线程环境下可能出现的数据不安全问题。作者分析了问题原因,即多个线程并发访问共享资源导致的线程不安全条件,并介绍了Java中的`synchronized`关键字来解决这个问题。通过将同步锁对象改为类级别的公共对象,成功避免了同一张票被多次售出的情况,实现了线程安全的售票程序。

1343

被折叠的 条评论
为什么被折叠?



