我正在阅读这本书" Java Concurrency In Practice"。在第二章中,我阅读了声明
任何单线程程序也是有效的多线程程序
我无法理解这句话。
请分享您的想法,以便清除我的困惑。提前谢谢。
答案 0 :(得分:3)
请注意,该语句并不意味着任何正确的单线程程序也是正确的多线程程序,作者只是声明可以转换任何单线程程序在多线程环境中执行。 / p>
但是,如果程序在单线程环境中已经不是正确,那么在更复杂的多线程环境中它可能不正确。
从书中可以看出:
由于任何单线程程序也是有效的多线程程序 程序,如果它甚至不正确,它就不能是线程安全的 单线程环境。
如果对象正确实现,则不会执行任何操作调用 公共方法和公共领域的读取或写入应该能够 违反任何不变量或后置条件。没有一套 在a的实例上顺序或同时执行的操作 线程安全类可能导致实例处于无效状态。
而且:
如果松散使用"正确性"在这里困扰你,你可能更喜欢 把线程安全类看作是一个不再破坏的类 并发环境比单线程环境。
@yshavit 在您考虑多线程正确性之前,请确保您至少具有单线程正确性。
答案 1 :(得分:2)
任何单线程程序也是有效的多线程程序
这基本上意味着任何单线程程序都可以在多线程上下文中使用。以下面的代码为例:
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
永远不应该小于零,然而,他们没有采取任何措施来强制执行此要求。从预期的角度来看,这个程序在单线程上下文中主要是不正确的(iCantBeNegatvie
如果doSomething
被连续11次或更多次调用将是< 0),这是最多的在多线程环境中肯定是不正确的。
答案 2 :(得分:1)
"任何单线程程序也是一个有效的多线程程序"
在没有阅读本书和阅读本节的情况下,在JVM中运行时,单线程应用程序实际上是多线程的有很多种方式。在JVM启动时,有许多JVM特定的线程被分叉。它们包括gc线程,终结器,JMX线程(如果启用)等。这些线程在后台运行,以帮助JVM高效运行。
例如,在我的OSX框中,默认情况下会分叉以下线程:
此外,当运行用户应用程序代码的主线程遇到synchronized
块或访问库或JDK中的volatile
字段时,主线程会经历内存障碍,获取和释放锁等就像多线程应用程序一样。这可能是作者引用的内容。
最后,重要的是要认识到“重入”这个术语"是在线程概念被发明之前创建的。由于递归方法或中断处理程序,代码需要正确编写为可重入,这意味着代码可以输入两次,即使它永远不是多个"线程"。在上下文切换,交换/输出,缓存等等之前,需要编写适当的可重入代码。是的,我在这里显示我的年龄。