zoukankan      html  css  js  c++  java
  • 并发编程日记-线程不安全的危害

    计数器

    @WebServlet(name = "HelloServlet", urlPatterns = {"/hello"})
    public class HelloServlet extends HttpServlet {
    
        private static final Logger LOG = Logger.getLogger(HelloServlet.class.getName());
    
        private Integer count = 0;
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            ++count;
            processRequest(request, response);
            LOG.info(String.format("计数 %d", count));
        }
    }
    
    

    按常理多少次请求后就会打印出计数多少。

    ab -n300 -c20 http://localhost:8080/servlet-demo/hello
    

    正常下,执行第一次 计数应为300

    事实上得到的却不是

    再执行..

    2 ~ 590
    3 ~ 879
    4 ~ 1170

    几乎没有规律,并不是预期的 300的倍数。

    解释

    实际上++count是一个读取-修改-写入的操作。

    假设线程A、B 同时读取到了值是m,同时写入+1后的值m+1。结果count = m+1,则事实上整个计数就少了1,应该为m+2。

    处理

    count声明为AtomicInter

        private Integer count = 0;
        private AtomicInteger atomicCount = new AtomicInteger(0);
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            ++count;
            processRequest(request, response);
            LOG.info(String.format("计数count %d", count));
            LOG.info(String.format("计数atomicCount %d", atomicCount.incrementAndGet()));
        }
    

    可以看到,AtomicInteger统计的是正确的了。

  • 相关阅读:
    Cocos2d-x 2.x项目创建
    Mac OS 使用Git
    Android Studio And Gradle
    Mac OS环境变量配置(Android Studio之Gradle)
    【Android UI】 Shape详解
    JS-OC通信之Cordova简介
    python类的定义和使用
    Android屏幕适配常识
    Python面试315题
    第十五篇 Python之文件处理
  • 原文地址:https://www.cnblogs.com/maitian2013/p/14510011.html
Copyright © 2011-2022 走看看