hrui0706 2023-02-16 22:23 采纳率: 20%
浏览 31
已结题

java并发安全问题回答下

下面这段代码有没有安全问题,测试了半天和我想法不太一样,还是我没有测出来

public class Test {
    public static void main(String[] args) {
        Table table=new Table();
        Thread t1 = new Thread(){
            public void run(){
                while(true){
                    int bean = table.getBean();
                    Thread.yield();
                    System.out.println(getName()+":"+bean);
                }
            }
        };
        Thread t2 = new Thread(){
            public void run(){
                while(true){
                    int bean = table.getBean();
                    Thread.yield();
                    System.out.println(getName()+":"+bean);
                }
            }
        };
        t1.start();
        t2.start();
    }
}
class Table{

    User user=new User();

    public  int getBean(){
        return user.getBean();
    }
}

class User{
    private int beans = 20;

    public int getBean(){
        if(beans==0){
            throw new RuntimeException("没有豆子了!");
        }
        Thread.yield();
        return beans--;
    }
}

  • 写回答

4条回答 默认 最新

  • zmy1127 2023-02-17 13:36
    关注

    这段代码可能存在并发安全问题。具体来说,如果多个线程同时执行 getBean() 方法,那么可能会出现以下两个问题:

    1.竞态条件:如果多个线程同时读取 beans 的值,然后将其递减并返回结果,那么可能会出现竞态条件,导致多个线程返回相同的 beans 值,而且这个值没有被正确递减。这会导致最终的结果不正确。

    2.非原子操作:递减操作不是原子操作,需要多条指令执行,因此多个线程同时执行时可能会导致线程安全问题,也就是说某个线程的递减操作被其他线程所覆盖,从而导致最终结果不正确。

    虽然 getBean() 方法内部有一个 Thread.yield() 方法,可能会让当前线程让出 CPU 资源,但这并不能保证安全性,因为即使当前线程让出了 CPU,其他线程仍然可能会抢占 CPU,从而导致上述问题。因此,需要对 getBean() 方法进行同步,以确保多个线程不会同时执行这个方法。

    一种简单的解决方案是将 getBean() 方法声明为 synchronized 方法,这样多个线程就不能同时进入这个方法,从而避免了上述问题。修改后的代码如下:

    
    class Table{
    
        User user=new User();
    
        public synchronized int getBean(){
            return user.getBean();
        }
    }
    
    class User{
        private int beans = 20;
    
        public synchronized int getBean(){
            if(beans==0){
                throw new RuntimeException("没有豆子了!");
            }
            Thread.yield();
            return beans--;
        }
    }
    
    

    这样就可以保证线程安全了。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 2月25日
  • 已采纳回答 2月17日
  • 创建了问题 2月16日

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘