zoukankan      html  css  js  c++  java
  • 【java】锁对象状态的改变会导致非线程安全

    问题描述

    使用synchronized在一个非final对象上加了锁之后,在synchronized体(同步代码块)中,将该对象的值(状态)改变之后,会导致线程不安全,即其他线程会拿到改变之后对象的锁,从而进入同步代码块。

    场景设计

    public class TestLock extends Thread{
        private AAA aaa;
         
        public TestLock(AAA aaa) {
            this.aaa = aaa;
        }
     
        @Override
        public void run() {
            this.aaa.lockMethod();
        }
     
        public static void main(String[] args) {
            AAA aaa = new AAA();
            Thread a1 = new TestLock(aaa);
            Thread a2 = new TestLock(aaa);
            a1.start();
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            a2.start();
        }
    }
     
    class AAA{
        private Boolean lock = true;
     
        public void lockMethod() {
            synchronized (lock) {
                lock = !lock;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(lock);
            }
        }
    }

    场景说明

    两个线程a1,a2,访问同一个AAA对象aaa(临界资源),AAA中的lockMethod方法中是一个同步代码块,锁加在非final的lock对象上,在同步代码块中改变lock对象的值。main函数中500ms的休眠是能够让线程a1先获得lock的锁,线程a1先访问同步代码块,将lock的值变成false,接着休眠一秒。

    假设

    如果lock值的改变不会影响线程安全的特性,那么线程a2拿不到lock的锁,在休眠结束之后,应该输出false,然后,线程a2拿到lock锁,进入同步代码块,将lock的值变成true,然后休眠一秒,休眠结束后,输出lock的值true,即输出的两个值是false和true。

    程序运行结果

    true和true

    程序结果分析

    第一个的输出结果是true,说明,线程a1进入同步代码块之后,将lock的值变成false,进入休眠,线程a2能够拿到修改后的lock对象的锁,进入同步代码块,将lock的值变成true,然后线程a2进入休眠,线程a1休眠结束之后,输出被线程a2修改之后的lock值true,然后,线程a2休眠结束之后,同样输出true,符合程序输出结果。

    总结与注意

    对于非对象上的锁,在同步代码块中修改起状态后,会导致线程不安全,即其他线程会拿到修改后的对象上的锁。

    对于需要加锁的对象,可以设置成final,这样就避免了对其的修改,如果是非final的对象,需要做到在同步块中避免对锁对象的修改。

  • 相关阅读:
    (转)创建Windows服务(Windows Services)N种方式总结
    无法加载协定为“ServiceReference1.xxxxxx”的终结点配置部分,因为找到了该协定的多个终结点配置。请按名称指示首选的终结点配置部分。
    《App架构实践指南》
    Awesome Projects (汇聚全球所有🐮项目,你值得拥有)
    【公告】个人站点及系列文章
    Android+TensorFlow+CNN+MNIST 手写数字识别实现
    TensorFlow基础
    UiAutomator2.0升级填坑记
    那些年,从博客到出书的博主
    Appuim源码剖析(Bootstrap)
  • 原文地址:https://www.cnblogs.com/sqdmydxf/p/7767823.html
Copyright © 2011-2022 走看看