【问题标题】:Protection for thread safety保护线程安全
【发布时间】:2014-02-23 11:06:36
【问题描述】:

我了解publicprivate 关键字的基本知识(我仍然不确定protected 是做什么的)

我有一个关于“为线程安全保护数据成员”的问题。

例如,假设我有一个扩展 Thread 的类 MyClass,属于该类的是一个名为 MyDataMember私有 数据成员。假设这个数据成员有 public 访问器和设置器函数,它们确保同步数据成员。

现在从“外部”的角度来看这一切都很好,因为其他线程只能在正确同步时设置和检索数据成员。但是,within MyClass 的其他函数呢?假设我有另一个函数 within MyClass 称为 DoSomething。我知道我不应该尝试直接访问MyDataMember,但我可能会不时忘记调用访问器/设置器方法并直接访问/设置数据成员。

我的问题是: 有没有一个关键字可以用来声明函数成员对某些数据成员的独占访问权?这样,如果我“不小心”从没有独占访问权限的方法直接访问数据成员,则会发生错误。我只是认为这会使开发过程中的事情变得更安全(至少对我而言!)

【问题讨论】:

  • 是的,MyClass 中的访问器/设置器函数使用 synchronized 关键字,效果很好。但我想知道是否有办法阻止从MyClass 中的方法直接访问MyDataMember,而不是访问器/设置器方法。
  • 关于你我的问题是一部分:例如:private int i; accessor 和 setter/mutator 也是方法(就像任何其他非静态方法一样)。没有办法阻止方法直接访问同一个类的变量。
  • 不,没有办法做到这一点。也许你想使用AtomicReference
  • 好的,谢谢您的信息。我不认为有,但不确定。将使开发更容易,因为编译器可以标记对数据成员 IMO 的非法访问。
  • 在 C++ 中,这样做的方法是将您需要保护的成员包装在它自己的类中,并且该类根本不允许您访问或修改该成员,除非您将其传递给它一个引用到你的锁。所以没有办法编写代码来访问没有锁的成员。

标签: java multithreading


【解决方案1】:

不,没有。

Protected 允许继承该类的类修改变量。

如果您想保护您的数据,请将其放在具有私有成员的单独类中,那么您只能使用 setter 和 getter。

【讨论】:

  • 这似乎是实现我所追求的一种方式。保持所有数据成员仅由一个类中的不同线程访问(作为私有成员),并仅在该类中实现访问器/设置器方法。谢谢。
  • 线程安全与访问修饰符无关。限制访问可以更轻松地确保所有访问都是线程安全的,但这仍然是您需要做的事情。
【解决方案2】:

关于要从不同线程访问的变量的可变关键字提示。

volatile int a;

您需要使用 synchronized 关键字进行访问,以使主体(或方法)在变量周围成为线程安全的。

// in thread 1
sycnhronized(lockedItem)
{
       a++; // just a++ alone may not be tread-safe because being non-atomic


}

// in thread 2
sycnhronized(lockedItem)
{
       a--; // just a-- alone may not be tread-safe because being non-atomic


}

【讨论】:

    【解决方案3】:

    受保护的关键字

    关于protected 关键字,请在此处阅读更多内容:

    短版:标记为protected 的方法/字段可以被子类和同一个包中的类访问。

    同步

    我认为您混淆了这些术语(或者我没有正确理解您的问题)。仅仅因为您为类中的字段创建了 setter 或 getter,就不能保证同步。但是,如果将 synchronized 关键字添加到方法签名 (public synchronized void doSomething()),则可以保证在任何给定时间只有一个线程运行该方法。对doSomething() 的其他调用将阻塞,直到运行该方法的线程离开该方法。

    如果您想确保所有线程都看到对(例如)不可变对象(创建后无法更改的对象)的更新引用,可以使用volatile 关键字。如果您有两个线程修改public String value;,如果您没有volatile 关键字,第一个线程可能看不到第二个线程已更新引用。在此处阅读更多信息:When exactly do you use the volatile keyword in Java?

    我不确定这是否会对您的示例有所帮助,因为您要求对成员变量进行“独占访问”。一般来说,我会尽量避免将主动对象(线程)与被动对象(数据)混合。也许您可以改为使MyDataMember 线程安全(也许通过使用synchronized),而您不需要关心如何访问它?

    【讨论】:

    • 感谢您提供额外信息。我想我的问题可以改写为“可以将函数成员指定为对某些数据成员具有独占访问权限吗?”这样,只有访问器/设置器方法可以被授予访问某些数据成员的权限,这将 IMO 提高定义数据成员的类中数据成员的线程安全性。
    • 例如,假设有一个exclusive 关键字。对于数据成员 exclusive 意味着 private 并且只能由 exclusive 函数成员访问。 exclusive 函数成员意味着 public 并且可以访问 exclusive 数据成员。不允许非exclusive 函数成员访问exclusive 数据成员。
    • 我明白了,但是正如您已经回答的那样,没有这样的关键字:) 我认为 Java 解决方案是将您想要使用 exclusive 关键字的所有内容分离到一个单独的对象中(正如您所描述的那样,排他性和非排他性数据之间不应该有任何通信)。
    • @joscarsson 是的。我不确定是否想检查一下-我对Java编程TBH一无所知! :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    • 1970-01-01
    相关资源
    最近更新 更多