读完了《Java并发编程实践》这本书以后,以为对一般的线程安全问题有一个大概的理解,但是今天遇到的这个问题着实非常神奇,在书中也没有被提到过,这里特别记录下来。
public class Test {
public void test1(O o) throws Exception {
System.out.println("begin o:" + o.getId() + " " + o.getName());
if (o.getId() == 1) {
Thread.sleep(10000);
System.out.println("o1:" + o.getId() + " " + o.getName());
}
if (o.getId() == 2) {
System.out.println("o2:" + o.getId() + " " + o.getName());
}
System.out.println("end o:" + o.getId() + " " + o.getName());
}
public static void main(String[] args) throws Exception {
final O o1 = new O(1, "o1");
Thread t1 = new Thread() {
@Override
public void run() {
try {
Test test = new Test();
test.test1(o1);
} catch (Exception e) {
e.printStackTrace();
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
try {
o1.setId(2);
o1.setName("o2");
Test test = new Test();
test.test1(o1);
} catch (Exception e) {
e.printStackTrace();
}
}
};
t1.start();
Thread.sleep(10);
t2.start();
}
}
class O {
public O(int id, String name) {
super();
this.id = id;
this.name = name;
}
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
两个线程先后启动,传入的是不同状态的同一对象。在test1方法的第一条打印中可以看出来,参数对象的状态是不同的,但是当第一个线程在第一个判断处休眠第二个线程开始执行以后,第一个线程打印出来的状态就和之前不一致了,其状态和第二个参数对象的状态一样。按照理论,方法执行以后,JVM会在独立的线程中压入一个方法栈,栈中会包含一个方法执行所需要的所有元素(包括代码和参数),这里为什么会出现方法执行到一半的时候参数状态改变呢?
推测:因为方法栈中压入的是一个对象的指针,而不是整个对象,所有当对象的状态被改变的时候还是可以第一时间被独立线程所察觉,所以尽管已经进入了方法栈,还是会引起对象状态的改变。
以后在处理多线程的问题时,必须要所用无状态Immutable的VO对象。这样才能保证线程安全
分享到:
相关推荐
4. **安全控制**:考虑到“神奇”一词,这个系统可能具有高级的安全特性,如端到端加密、身份验证、访问控制、防火墙策略等,确保数据在传输过程中的安全性。 5. **性能优化**:为了实现高效传输,系统可能采用了...
"网盘下载神奇.rar"这个压缩包文件,很可能包含了一款名为PanDownload的软件,这是一款专为解决百度网盘下载速度问题而设计的第三方工具。PanDownload能够帮助用户绕过官方的限速策略,实现接近满速的下载速度,极大...
X-Scan 采用多线程方式对指定 IP 地址段(或单机)进行安全漏洞检测,支持插件功能。扫描内容包括:远程服务类型、操作系统类型及版本、各种弱口令漏洞、后门、应用服务漏洞、网络设备漏洞、拒绝服务漏洞等二十几个...
4. **多线程**:Java内置了对多线程编程的支持,允许开发者创建同时执行的多个线程。 5. **网络编程**:Java提供了丰富的网络通信API,使得开发网络应用变得容易。 6. **安全性**:Java提供了一个安全
`paint`方法通常不直接由程序员调用,而是由Java事件调度线程(Event Dispatch Thread, EDT)在需要时调用,确保了界面的线程安全。在`paint`方法内部,它首先调用`paintComponent`、`paintBorder`和`paintChildren`...
X-Scan采用多线程方式对指定IP地址段(或单机)进行安全漏洞检测,支持插件功能,提供了图形界面和命令行两种操作方式,扫描内容包括:远程操作系统类型及版本,CGI漏洞,IIS漏洞,RPC漏洞,SQL-SERVER、FTP-SERVER等...
在“通往Android的神奇之旅第九章Network.rar”这个压缩包中,主要涵盖了Android应用程序开发中的一个重要领域——网络编程。在Android应用开发中,网络功能是不可或缺的,它使得应用程序能够与互联网上的服务器进行...
然而,需要注意的是,由于Android的安全机制,直接在主线程上执行XML解析可能会导致ANR(应用无响应)错误,因此应当在后台线程如AsyncTask中进行。 在使用XStream时,我们还需要关注一些最佳实践。例如,为了提高...
并且它们表现得“神奇”,那么可能它们采用了并发控制策略,如synchronized关键字、Lock接口(如ReentrantLock)或者并发工具类(如Semaphore、CountDownLatch),来确保线程安全并优化性能。 程序的运行状态可能是...
在多线程编程中,确保线程安全是至关重要的,而这通常涉及到同步机制。本压缩包"MutexSpinlockAndCAS.tar.gz"包含了关于互斥锁(Mutex)、自旋锁(Spinlock)以及比较器和交换(Compare-And-Swap, CAS)操作的源码...
在IT领域,尤其是逆向工程和恶意软件分析中,"PE可执行文件超强查壳神奇/Die最新版2.0"是一款重要的工具,主要用于检测和处理PE(Portable Executable)格式的可执行文件上的加壳技术。PE文件是Windows操作系统中...
Java是一种广泛使用的编程语言,以其跨平台、高性能、安全性和稳定性而备受青睐。本实例集主要针对那些刚开始接触Java或者希望巩固基础的学员。它将带领你逐步探索Java的基础语法、类和对象、封装、继承、多态等核心...
《VM Tweaker 0.12.1.21:深度优化虚拟机的神奇工具》 VM Tweaker,一个在虚拟机领域广受好评的强大工具,版本号0.12.1.21,以其丰富的功能和高效的操作性赢得了用户的青睐。这个小巧的压缩包,虽然只有两个主要...
6. 并发处理:通过Rust的`async/await`和tokio库实现多线程或多任务并发,加快数据处理速度。 项目的源代码位于"randbats-winrates-main"目录下,包含了整个应用的实现细节。开发者可以通过阅读源码学习如何用Rust...
SqlSession对象是SqlSessionFactory的非线程安全的实例,每次数据库交互都应创建一个新的SqlSession。 3. **SqlSession**: SqlSession提供了与数据库进行交互的方法,如执行SQL语句、提交事务、回滚事务等。它也是...
而双亲委派模型是类加载器之间关系的典型设计,防止类的重复加载和保证核心类库的安全性。 垃圾收集是JVM性能优化的关键。常见的垃圾收集器有Serial、ParNew、Parallel Scavenge、CMS、G1等,它们各有优缺点,如...
3. **SqlSession**:每个线程都应该有自己的SqlSession实例,它是非线程安全的,用于执行数据库操作,使用完毕后必须关闭。 4. **Mapper接口**:这是用户自定义的接口,用于定义数据库操作方法。Mybatis通过动态代理...
通过以上分析,我们可以看到,开发Java仿QQ聊天工具不仅需要理解MVC模式,还需要掌握网络编程、数据持久化、安全性和多线程等核心技术。这个简单的易学版项目对于初学者来说是一个很好的实践平台,可以帮助他们将...
"JAVA编程精灵"是一款专为Java初学者和资深开发者设计的实用工具,旨在提供一个安全、无毒的环境,让学习者能够进行编程练习和项目开发。这款软件可能包含了丰富的编程资源、实例代码、测试环境以及可能的调试功能,...
Kotlin的设计目标是提供一种简洁、安全且富有表现力的语法,同时兼顾可空安全性,避免空指针异常,这在Java中是一个常见的问题。Kotlin的出现,为Android开发者提供了新的选择,逐渐成为Android开发的首选语言。 在...