多线程:三大不安全案例

三大不安全案例

  • 1、不安全的买票
    (线程不安全,有负数)
package jingcheng.test.syn;
//不安全的买票
public class UnsafeBuyTicket {
    public static void main(String[] args) {
        BuyTicket station = new BuyTicket();

        new Thread(station,"苦逼的我").start();
        new Thread(station,"牛逼的你们").start();
        new Thread(station,"可恶的黄牛党").start();

    }
}
class BuyTicket implements Runnable{
    //票
    private int ticketNums = 10;
    boolean flag = true;//外部停止方式
    @Override
    public void run() {
        //买票
        while(flag){
            buy();
        }
    }
    private void buy(){
        //判断是否有票
        if(ticketNums<=0){
            flag = false;
            return;
        }
        //模拟延时
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        //买票
        System.out.println(Thread.currentThread().getName()+"拿到"+ticketNums--);
    }
}

牛逼的你们拿到10
苦逼的我拿到10
可恶的黄牛党拿到9
苦逼的我拿到8
可恶的黄牛党拿到8
牛逼的你们拿到7
牛逼的你们拿到6
可恶的黄牛党拿到5
苦逼的我拿到4
牛逼的你们拿到3
可恶的黄牛党拿到2
苦逼的我拿到1
可恶的黄牛党拿到0
牛逼的你们拿到-1

Process finished with exit code 0

  • 2、不安全的取钱(sleep 可以放大问题的发生性)
package jingcheng.test.syn;
//不安全的取钱
//两个人去银行取钱,账户
public class UnsafeBank {
    public static void main(String[] args) {
        //账户
        Account account = new Account(100,"结婚基金");
        Drawing you = new Drawing(account,50,"你");
        Drawing girlFriend = new Drawing(account,100,"girlFriend");
        you.start();
        girlFriend.start();
    }
}
 //账户
class Account{
    int money; //余额
     String name;//卡名

     public Account(int money,String name) {
         this.money = money;
         this.name = name;
     }
 }
 //银行:模拟取款
class Drawing extends Thread{
    Account account;//账户
     //取了多少钱
     int drawningMoney;
     //现在手里有多少钱
     int nowMoney;
     public Drawing(Account account,int drawningMoney,String name){
         this.account = account;
         this.drawningMoney = drawningMoney;
         this.nowMoney = nowMoney;

     }
//取钱
     @Override
     public void run() {
         //判断有没有钱
         if(account.money-drawningMoney<0){
             System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
             return;
         }
         try {
             Thread.sleep(1000);
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
         //卡内余额=余额-你取的钱
         account.money = account.money-drawningMoney;
         //你手里的钱
         nowMoney = nowMoney+drawningMoney;
         System.out.println(account.name+"余额为:"+account.money);
         //Thread.currentThread().getName() = this.getName()
         System.out.println(this.getName()+"手里的钱:"+nowMoney);
     }
 }

结婚基金余额为:-50
Thread-1手里的钱:100
结婚基金余额为:50
Thread-0手里的钱:50

Process finished with exit code 0

  • 3、线程不安全的集合
package jingcheng.test.syn;

import java.util.ArrayList;
import java.util.List;

//线程不安全的集合
public class UnsafeList {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());
            }).start();
            
        }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(list.size());
    }
}

9947

Process finished with exit code 0

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 假设我们有一个多线程应用程序,每个线程都需要使用相同的 API token 来访问某个服务。我们可以使用线安全的方式来共享这个 token。 一种方法是将 token 存储在一个全局变量中,并使用锁来保证每个线程访问该变量时的原子性。例如,我们可以使用 Python 中的 threading 库: ```python import threading TOKEN = "my_api_token" TOKEN_LOCK = threading.Lock() def use_token(): with TOKEN_LOCK: # 使用 TOKEN 访问 API pass # 创建多个线程并启动它们 threads = [] for i in range(10): thread = threading.Thread(target=use_token) thread.start() threads.append(thread) # 等待所有线程完成 for thread in threads: thread.join() ``` 在上面的示例中,我们将 token 存储在全局变量 TOKEN 中,并使用 threading.Lock() 创建一个锁对象 TOKEN_LOCK。然后在每个线程中,我们使用 with 语句来获取锁对象,这样可以确保每个线程在访问 TOKEN 变量时是安全的。 当一个线程获取到锁对象时,其他线程将被阻塞,直到该线程释放锁对象。这样可以确保每个线程都能够安全地访问 TOKEN 变量,而不会与其他线程产生冲突。 需要注意的是,使用全局变量和锁来共享 token 只是其中的一种解决方案。我们还可以考虑使用线程本地存储(Thread-Local Storage)或者单例模式等其他的技术来实现共享 token 的方式。具体的实现方式会根据具体的应用场景和编程语言而有所不同。 ### 回答2: 多线程公用token案例中,多个线程需要同时访问一个共享的token资源。在这种情况下,需要确保多个线程能够正确地并发访问和更新token,且不会出现数据竞争和错误的结果。 首先,可以创建一个全局的token变量,作为公共资源。在访问和更新token时,需要采取适当的同步机制来保证线安全。可以使用互斥锁或信号量来实现线程间的互斥操作。在每个线程中访问或更新token之前,需要先获取锁或信号量,操作完成后再释放锁或信号量。 其次,需要考虑在多线程环境下对token的使用和更新策略。可以使用条件变量或线程信号量来控制线程的执行顺序和条件等待。例如,可以设定一个条件,当token的值满足一定条件时,线程可以执行相应的操作,否则需要等待条件满足。这样可以确保线程在合适的时机执行,避免了不必要的等待和资源浪费。 另外,还可以利用队列或缓冲区来处理并发请求。当多个线程同时请求token时,可以将请求按照先后顺序加入到队列或缓冲区中,并由一个线程作为调度者负责分发token。这样可以避免竞争和冲突,并确保所有线程都能够公平地使用token。 综上所述,多线程公用token案例需要通过合适的同步机制、条件等待和任务分发等策略来保证线安全和公平性。通过合理的设计和实现,可以确保多线程能够正确地并发使用共享的token资源,提高系统的性能和可靠性。 ### 回答3: 多线程公用token案例是指多个线程同时操作一个共享的token对象。在这种情况下,线程之间会竞争和共享token的资源,可能会产生冲突和并发安全问题。 为了解决多线程公用token的问题,可以采取以下方法: 1. 锁机制:可以使用互斥锁或信号量等机制来保证多个线程对token对象的访问互斥进行,每次只有一个线程能够获得token的使用权,其他线程需要等待。这样能够避免并发冲突问题。 2. 线安全的数据结构:可以使用线安全的数据结构来管理token,例如使用ConcurrentHashMap或ConcurrentLinkedQueue等,并采用原子操作来实现对token的安全访问。 3. 同步方法或关键字:可以使用synchronized关键字修饰对token的操作方法,使得每个线程在执行该方法时,都会获得token的独占访问权,其他线程需要等待。 4. 使用线程池:可以使用线程池来管理多线程的执行,通过控制线程池中线程的数量和调度机制,来控制并发的访问token对象,从而减少冲突。 5. 分配独立的token对象:可以为每个线程分配独立的token对象,让每个线程操作自己的token对象,避免多个线程之间的竞争和冲突。 总之,多线程公用token的案例需要注意并发安全问题,并采取相应的安全措施,以保证线程之间对token的访问安全和正确。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值