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#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。