沈山南丶 2022-05-02 17:56 采纳率: 50%
浏览 14
已结题

为什么变量上锁了,取的值还不对

/**

  • 使用的对象

  • /
    class Romm{
    private int count =0;

    public void increment(){

      synchronized (this){
          count++;
      }
    

    }

    public void decrement(){

      synchronized (this){
          count--;
      }
    

    }
    //取值也得上锁,防止increment和decrement没有执行完毕就取值,
    public int getCount(){

      synchronized (this){
          return count;
      }
    

    }
    }

public static void main(String[] args) throws InterruptedException {
/**

  • 两个线程,一个自加一个自减

  • /

    Thread t3 = new Thread(() -> {
           for (int i = 0; i < 50000000; i++) {
               romm.increment();
           }
    
       });
       Thread t4 = new Thread(() -> {
           for (int i = 0; i < 50000000; i++) {
               romm.decrement();
           }
       });
       t3.start();
       t4.start();
      //确保t3t4线程进入运行态
       Thread.sleep(200);
       int count = romm.getCount();
       log.debug("count:{}",count);    //17:42:46.237 [main] DEBUG c.SynchronizedTest - count:250137 
    

    }
    count难道不应该是50000000或者-50000000或者0吗? 主线程执行romm.getCount()时,不会被阻塞吗?因为锁已经被t3,t4其中一个占用了,当t3,t4其中一个使用完毕,主线程和其中一个线程去抢占锁,最后结果不是50000000或者-50000000或者0吗?

  • 写回答

2条回答 默认 最新

  • 溪风沐雪 2022-05-02 21:06
    关注

    线程同步实质上是一个等待机制。线程同步时会将多个线程放入对象等待池中进行排队(队列),等待前一个线程执行操作完毕,再有下一个线程进行执行操作。每个对象都有一个独有的锁(排他锁),每个线程执行时都会获得对象的排他锁,这样只有获得锁的线程可以对对象进行操作,执行结束后排他锁被下一个线程获得。总结来说,线程同步的形成条件就是:队列+锁。
    你所谓的占用是在每一轮循环中占用,循环完毕就释放锁了,别的线程就可以调用变量了,所以最终是3个线程在竞争,没有那个线程能独占

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

报告相同问题?

问题事件

  • 系统已结题 5月13日
  • 已采纳回答 5月5日
  • 创建了问题 5月2日

悬赏问题

  • ¥15 多址通信方式的抗噪声性能和系统容量对比
  • ¥15 winform的chart曲线生成时有凸起
  • ¥15 msix packaging tool打包问题
  • ¥15 finalshell节点的搭建代码和那个端口代码教程
  • ¥15 Centos / PETSc / PETGEM
  • ¥15 centos7.9 IPv6端口telnet和端口监控问题
  • ¥20 完全没有学习过GAN,看了CSDN的一篇文章,里面有代码但是完全不知道如何操作
  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 海浪数据 南海地区海况数据,波浪数据
  • ¥20 软件测试决策法疑问求解答