【问题标题】:How provide in java atomic read/write of 2 variables together?java - 如何在java中同时提供2个变量的原子读/写?
【发布时间】:2012-02-10 09:52:43
【问题描述】:

在我的课堂上,我的代码如下:

int counter1;
int counter2;

public void method1(){
 if (counter1>0) {
  ...........do something
   if (counter2>0) {
    ....do something else
    }
}

public void method2() {
  counter1=0;
  counter2=0;
}

我需要将两个计数器设置在一起。恐怕只有在设置 counter1 后才能调用 OS 到 method1。有可能吗? 谢谢。

【问题讨论】:

标签: java multithreading concurrency atomic operation


【解决方案1】:

要么使用 synchronized 关键字作为其他答案的建议,要么使用 ReentrantReadWriteLock 如果您对计数器的读取多于写入,以获得更好的性能。你可以在这里阅读关于锁的信息http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html

private int counter1;
private int counter2;
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock r = rwl.readLock();
private final Lock w = rwl.writeLock();

public void method1(){
   r.lock();
   try { 
     if (counter1>0) {
        ...........do something
     if (counter2>0) {
        ....do something else
     }
   } finally { r.unlock(); }

}

public void method2() {
  w.lock();
  try { 
    counter1=0;
    counter2=0; 
  } finally { w.unlock(); }

}

【讨论】:

  • 嗯!一个计数器改变而另一个不改变呢?你没有阻止它!
  • 我不明白你的意思,示例中的计数器受 ReadWriteLock 保护。
  • 它们受到保护,不会被其他线程访问。但并非例外。因此,您的代码不会以原子方式阻止两个操作。
  • @Gangnus 什么异常,将某些内容设置为0 不会抛出一个?并且没有atomic 方法来更新标准Java 中的多个变量。 STMs 都是研究级别的,而不是生产就绪的 AFAIK。
  • 1.做某事可以抛出异常。 2. 但是是的,在 Java 中是可能的。我们还没有现成的结构,但我们可以对其进行编程。 SO上最好的(虽然不是理想的)算法在这里:stackoverflow.com/a/16906229/715269
【解决方案2】:

当然,只需使用 synchronized 关键字:

private final Object LOCK = new Object();
int counter1;
int counter2;

public void method1() {
  synchronized(LOCK) {
     if (counter1>0) {
      ...........do something
       if (counter2>0) {
        ....do something else
       }
    }
}
public void method2() {
  synchronized(LOCK) {
    counter1=0;
    counter2=0;
  }
}

一些提示:

使用私有对象进行同步,而不是将方法标记为同步。这可以防止你类外部的东西抓住锁和拖延东西。

确保您使用同步关键字无处不在,并确保您始终在同一个对象上同步。如果您忘记执行其中任何一项操作,两个进程可以同时访问这些字段。

当心死锁。在一个完美的世界里,你应该编写单元测试来确保锁定按照你想象的方式工作。

【讨论】:

  • 是的。但这是可能的。一种方法是注入你的锁,而不是使用 synchronized 关键字。
  • 不明白,这里锁定私有和方法有什么区别?线程 1 可以调用方法 1,线程 2 可以调用方法 1,其中一个会被阻塞 - 两种方法都没有区别(方法与私有变量);我唯一能看到的是你想为类中的不同数据位允许不同的锁(这是合理的,但你必须知道你在做什么......) - 我会争辩说数据属于不同的类
  • @Nim:不同的是,如果你同步方法,方法所属的对象被用作锁。任何引用该对象的人也可以将此对象用作锁,这会严重破坏您的同步。这是一种防御性编码技术。
  • 那么一个计数器改变而另一个不改变呢?你没有阻止它!
【解决方案3】:

使用同步块或方法来包装对两个计数器的访问,记得使用同一个对象来锁定。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-20
    • 2017-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    相关资源
    最近更新 更多