仅使用不可变数据类型是否使Java程序线程安全?

如果我只使用不可变数据类型,我的Java程序是否可以线程安全?

任何其他因素都会影响线程安全吗?

****如果可以提供一个例子,将不胜感激。 谢谢!** **

线程安全是关于保护共享数据和不可变对象受到保护,因为它们是只读的。 除了创建它们之外,创建对象是线程安全的。

值得一提的是,设计一个只使用不可变对象来实现线程安全的大型应用程序将很困难。

这是一个复杂的主题,我建议你阅读Java Concurrency in Practice ,这是一个非常好的起点。

这是真的。 问题是,在应用程序中仅使用不可变数据类型是一个非常严重的限制。 您不能拥有跨线程存在状态的任何持久对象。

我不明白你为什么要这么做,但这并没有让它变得那么真实。

详细信息和示例: http : //www.javapractices.com/topic/TopicAction.do?Id = 29

如果每个变量都是不可变的(一旦分配就不会改变),你确实会有一个简单的线程安全程序。

function编程环境利用了这一点。

但是,使用不是从头开始设计的语言进行纯函数式编程是非常困难的。

在纯函数程序中你不能做的事情的一个简单例子是使用循环,因为你不能增加一个计数器。 您必须使用递归函数来实现相同的效果。

如果你只是陷入线程安全和并发的世界,我会衷心地推荐Goetz的Java Concurrency in Practice 。 它是为Java编写的,但实际上它所讨论的问题也与其他语言相关,即使这些问题的解决方案可能不同。

不可变性允许对multithreading案例可能出错的某些事情进行安全保护。 具体来说,这意味着当第一个线程正在使用它时,一个线程可见的对象的属性不能被另一个线程更改(因为没有什么可以改变它,那么显然另一个线程不能)。

当然,这只适用于该对象。 如果还共享对该对象的可变引用,则某些跨线程错误的情况可能是由于在那里放置一个新对象(但不是全部),因为如果一个线程在已经被替换的对象上工作可能无关紧要,但那可能是至关重要的)。

总之,不变性应该被认为是确保线程安全的方法之一,但既不是唯一的方式,也不一定是足够的。

虽然不可变对象是线程安全的帮助,但您可能会发现“局部变量”和“同步”对于现实世界的编程更加实用。

任何程序状态的可变方面都不被一个线程访问的程序将是完全线程安全的,因为每个线程也可以是它自己的独立程序。 然而,有用的multithreading通常需要线程之间的交互,这意味着存在一些可变的共享状态。

安全高效的multithreading的关键是将可变性纳入正确的“设计级别”。 理想情况下,程序状态的每个方面都应该由一个不可变的根(*)可变引用来表示,该对象的可观察状态是不可变的。 一次只有一个线程可能尝试更改由特定可变引用表示的状态。 高效的multithreading要求程序状态中的“可变层”足够低,以便不同的线程可以使用它的不同部分。 例如,如果一个具有不可变的AllCustomers数据结构,并且两个线程同时尝试更改不同的客户,则每个都会生成一个AllCustomers数据结构的版本,其中包含自己的更改,但不包括其他线程的更改。 不好。 但是,如果AllCustomersCustomerState对象的可变数组,那么一个线程可以在AllCustomers[4]工作,而另一个线程可以在AllCustomers[9] ,而不会产生干扰。

(*)当状态方面变得相关时,根路径必须存在,并且在访问相关时不得更改。 例如,可以设计一个AddOnlyList ,它包含一个名为Arrthing[][] ,它被初始化为32。当第一个添加时, Arr[0]将使用CompareExchange初始化为一个数组16 thing 。 接下来的15件事就会进入那个arrays。 当添加第17个东西时, Arr[1]将使用CompareExchange初始化为大小为32的数组(它将保存新项目和之后的31个项目)。 当添加第49个东西时, Arr[2]将被初始化为64个项目。 注意,虽然thing本身和由此包含的数组不是完全不可变的,但只有第一次访问任何元素才是写入,一旦Arr[x][y]持有对某事物的引用,它将继续这样做只要Arr存在。