繁体   English   中英

将getter与输入处理方法分开的类可以被认为是“线程安全的”吗?

[英]Can a class with getters separate from input processing methods be considered “thread-safe”?

我正在读一本关于Java的书,有一个练习题,他们用一个私有变量声明了一个类,一个公共void方法做了一些昂贵的操作来计算然后设置私有变量,另一个公共方法返回私人变量。 问题是“如何使这个线程安全”,一个可能的答案是“同步两个方法中的每一个”,另一个可能的答案是“这个类不能成为线程安全的”。

我认为类不能成为线程安全的,因为即使你同步这两个方法,你可能会遇到Thread1会调用setter的情况,在Thread1可以调用getter之前,Thread2可能会执行并调用setter,这样当Thread1去检索结果会得到错误的信息。 这是看待事物的正确方法吗? 书中提出的正确答案是,通过同步这两种方法可以使类成为线程安全,现在我很困惑......

我认为类不能成为线程安全的,因为即使你同步这两个方法,你可能会遇到Thread1会调用setter的情况,在Thread1可以调用getter之前,Thread2可能会执行并调用setter,这样当Thread1去检索结果会得到错误的信息。 这是看待事物的正确方法吗?

你是对的。 无法保证线程不会在类中调用每个方法之间调用任何一种方法。

如果你想这样做,那将需要一个包装类。 所以如果带有getter和setter的类是这样的:

class Foo
{
    private static int bar;

    public static synchronized void SetBar(int z) { ... }
    public static synchronized int GetBar() { ... }
}

包装类看起来像这样:

class FooWrapper
{

    public synchronized int SetGetBar(int z)
    {
        Foo.SetBar(z);
        return Foo.GetBar();
    }

}

保证这一点的唯一方法是,如果你可以保证所有的调用都将通过你的包装类,而不是直接到类Foo。

当你使这两个同步时,getter和setter本身是线程安全的。 进一步来说:

  • 当您调用setter时,可以保证变量的值是方法完成时设置的值。
  • 当您调用getter时,可以保证返回值是您进行调用时变量的值。

    但是,使getter和setter 本身是线程安全的并不意味着应用程序作为一个整体 (即使用此类的任何东西)是线程安全的。 如果您的线程想要调用setter,那么在调用getter时获取相同的值,这涉及在不同级别上的同步。

    就线程安全性而言,线程安全类不需要控制如何调用其方法(例如,它不需要控制线程交换其调用的方式),但它需要确保它们何时 ,方法做他们应该做的事。

  • Java中的synchronized是一个对象范围的锁。 任何给定对象的一个synchronized方法一次只能在任何给定的线程上执行。 让我们来上课:

    class Foo
    {
        private int bar;
    
        public synchronized void SetBar() { ... }
        public synchronized int GetBar() { ... }
    }
    
    • 线程1调用SetBar() 线程1获取对象锁。
    • 线程2想要调用SetBar() ,但线程1持有锁。 线程2现在排队等待线程1将释放它时获取锁定。
    • 线程1完成执行SetBar()并释放锁。
    • 线程2立即获取锁并开始执行SetBar()
    • 线程1调用GetBar() 线程1现在排队等待线程2将释放它时获取锁定。
    • 线程2完成执行SetBar()并释放锁。
    • 线程1获取锁,执行GetBar() ,并完成它。

    你做了两次工作,但没有造成任何竞争条件。 两次工作可能会或可能不会是错误的,具体取决于它是什么。

    一个常见的模式是让一个线程产生内容,另一个线程做一些有用的东西。 这被称为生产者 - 消费者模式。 在这种情况下,对于谁或什么尝试SetBar()以及尝试GetBar()内容没有混淆。

    暂无
    暂无

    声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

     
    粤ICP备18138465号  © 2020-2024 STACKOOM.COM