单例Class A状态修改后的线程安全性技术问询
线程安全疑问:单例状态修改后的周期性调用问题
问题描述
我在项目里用了这样一个单例类:
Class A{ private boolean connected = false; public void doAction(){ if(connected){ //do something } else{ //do this } } public void setConnected(boolean flag) { this.connected = flag; } }
这个单例的setConnected()方法会在特定条件下触发(仅执行一次),doAction()方法由调度器周期性调用执行操作。我想知道:当单例对象的状态被修改后,是否存在线程安全相关问题?
回答
嘿,这个问题抓得很准,咱们来好好唠唠:
答案是存在线程安全问题,核心是变量的可见性问题。
Java的内存模型里,每个线程可能会将共享变量的副本缓存到自己的工作内存中。当执行setConnected()的线程修改了connected的值后,如果没有同步机制,这个更新不会强制立刻同步到主内存;而调度器线程在调用doAction()时,可能一直读取自己工作内存里的旧值(也就是初始的false),完全不知道状态已经被修改了——哪怕setConnected()只执行一次,也没法避免这个问题。极端情况下,调度器线程会永远走else分支,完全无视状态变更。
解决办法
针对你的场景(connected只被修改一次,后续只有读取操作),有几个轻量化且有效的方案:
- 给
connected加volatile关键字:
修改成private volatile boolean connected = false;。volatile的作用就是保证变量的可见性,禁止指令重排序,确保一个线程对变量的修改能立刻被其他线程感知到,而且性能开销极小,非常适合这种场景。 - 如果后续业务逻辑变复杂(比如
connected可能被多次修改,或者修改/读取有更复杂的原子操作),可以考虑:- 给
doAction()和setConnected()方法加上synchronized关键字,通过锁来保证线程间的同步; - 使用
AtomicBoolean类来封装状态,它自带原子性和可见性保障。
- 给
内容的提问来源于stack exchange,提问作者girish babu
相关产品推荐
相关产品推荐

