[英]How can any single-threaded program be a valid multithreaded program?
我正在阅读“Java Concurrency In Practice”一书。 在第二章中,我阅读了该声明
任何单线程程序也是一个有效的多线程程序
我无法理解这句话。
请分享您的想法,以便清除我的困惑。 提前致谢。
注意,该语句并不意味着任何正确的单线程程序也是正确的多线程程序,作者只是说明有可能将任何单线程程序转换为在多线程环境中执行。
但是,如果程序在单线程环境中已经不正确 ,那么在更复杂的多线程环境中它可能不正确。
从书中:
由于任何单线程程序也是有效的多线程程序,如果它在单线程环境中甚至不正确,则它不能是线程安全的。
如果一个对象被正确实现,则没有操作序列 - 对公共方法的调用以及对公共字段的读取或写入应该能够违反其任何不变量或后置条件。 在线程安全类的实例上顺序或并发执行的任何操作集都不会导致实例处于无效状态。
还有这个:
如果这里对“正确性”的松散使用困扰您,您可能更愿意将线程安全类视为在并发环境中不比单线程环境更糟糕的类。
@yshavit 在考虑多线程正确性之前,请确保至少具有单线程正确性。
任何单线程程序也是一个有效的多线程程序
这基本上意味着任何单线程程序都可以在多线程上下文中使用。 以下面的代码为例:
class A {
public void doSomething() { }
}
如果我们孤立地考虑上面的类,它显然是一个单线程程序; 但是,同样的程序也可以在多线程上下文中使用:
Thread thread1 = new Thread(new Runnable() { public void run() { A a = new A(); a.doSomething(); } }).start();
Thread thread2 = new Thread(new Runnable() { public void run() { A a = new A(); a.doSomething(); } }).start();
在书中谈到你没有问过的具体相关段落,但值得讨论:
在线程安全类的实例上顺序或并发执行的任何操作集都不会导致实例处于无效状态
让我们在课堂上添加一些状态:
class A {
int iCantBeNegative = 10;
public void doSomething() { --icantBeNegative; }
}
程序员的期望是iCantBeNegative
永远不应该小于零,然而,他们没有采取任何措施来强制执行这一要求。 由于从预期的角度看这个程序在单线程上下文中是不正确的(如果doSomething
连续被调用11次或者更多, iCantBeNegatvie
将<0),在多线程上下文中它绝对是不正确的。
“任何单线程程序也是一个有效的多线程程序”
在没有阅读本书并阅读本节的情况下,在JVM中运行时,单线程应用程序实际上是多线程的有很多种方式。 在JVM启动时,有许多JVM特定的线程被分叉。 它们包括gc线程,终结器,JMX线程(如果启用)等。 这些线程在后台运行,以帮助JVM高效运行。
例如,在我的OSX框中,默认情况下分叉以下线程:
此外,由于运行用户应用程序代码的主线程遇到synchronized
块或访问库或JDK中的volatile
字段,因此主线程会像多线程应用程序一样通过内存屏障,获取和释放锁等。 这可能是作者引用的内容。
最后,重要的是要意识到术语“可重入”是在线程概念被发明之前创建的。 由于递归方法或中断处理程序,代码需要正确编写为可重入,这意味着代码可以输入两次,即使它从不是多个“线程”。 在上下文切换,交换/输出,缓存等等之前,需要编写适当的重入代码。是的,我在这里显示我的年龄。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.