同步装饰器来替换线程安全类

您知道什么是线程安全吗? 如果没有,下面是一个简单的示例。 所有类都必须是线程安全的,对吗? 并不是的。 其中一些必须是线程安全的? 又错了。 我认为它们都不必是线程安全的,而它们都必须提供同步的装饰器。

阿拉丁(1992),罗恩·克莱门茨和约翰·马斯克

让我们从一个示例开始(顺便说一下,它是mutable ):

class Position {
  private int number = 0;
  @Override
  public void increment() {
    int before = this.number;
    int after = before + 1;
    this.number = after;
  }
}

您如何看待-它是线程安全的吗? 该术语指的是当同时由多个线程使用时,此类的对象是否将正确运行。 假设我们有两个线程在同一个对象position ,并在完全相同的时间调用它的方法increment()

我们希望两个线程结束时整数的number等于2,因为它们每个都会递增一次,对吗? 但是,这极有可能不会发生。

让我们看看会发生什么。 在两个线程中,启动时, before等于0 。 然后after将设置为1 。 然后,两个线程会做this.number = 1 ,我们将结束与1number ,而不是预期2 。 看到问题了吗? 在设计中存在此类缺陷的类不是线程安全的

最简单,最明显的解决方案是使我们的方法synchronized 。 这将确保无论有多少线程同时调用它,它们都将按顺序而不是并行进行:一个线程接一个线程。 当然,这将花费更长的时间,但是它将防止该错误的发生:

class Position {
  private int number = 0;
  @Override
  public synchronized void increment() {
    int before = this.number;
    int after = before + 1;
    this.number = after;
  }
}

保证无论有多少线程都不会中断的类称为线程安全

现在的问题是:我们是否必须使所有类都成为线程安全的,或者只使其中某些类成为线程安全的? 使所有类都无错误似乎更好,对吗? 为什么有人想要一个可能在某个时候破裂的物体? 好吧,不完全是。 记住,涉及性能方面的问题; 我们通常没有多个线程,并且我们始终希望我们的对象尽可能快地运行。 线程间同步机制肯定会使我们慢下来。

我认为正确的方法是开设两个班级。 第一个不是线程安全的,而另一个是同步的decorator ,它看起来像这样:

class SyncPosition implements Position {
  private final Position origin;
  SyncPosition(Position pos) {
    this.origin = pos;
  }
  @Override
  public synchronized void increment() {
    this.origin.increment();
  }
}

现在,当我们需要position对象是线程安全的时,我们可以使用SyncPosition装饰它:

Position position = new SyncPosition(
  new SimplePosition()
);

当我们需要一个简单的简单位置而没有任何线程安全性时,我们可以这样做:

Position position = new SimplePosition();

我认为使类功能既丰富线程安全是违反了那个著名的单一责任原则的

顺便说一句,这个问题非常接近防御性编程和验证程序之一。

您可能还会发现这些相关的帖子有趣: 您如何使用InterruptedException? ; 为什么InputStream设计错误 ; 限制Java方法执行时间如何实现一个迭代适配器 ; 通过验证装饰器进行防御性编程 ;

翻译自: https://www.javacodegeeks.com/2017/01/synchronized-decorators-replace-thread-safe-classes.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值