Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程同步,最佳并发实用程序,读取操作_Java_Multithreading - Fatal编程技术网

Java线程同步,最佳并发实用程序,读取操作

Java线程同步,最佳并发实用程序,读取操作,java,multithreading,Java,Multithreading,我有一个与java线程相关的问题 举一个非常简单的例子,假设我有两个线程 线程运行StockReader类实例 运行StockAvgDataCollector类实例的线程B 在线程B中,StockAvgDataCollector连续收集一些市场数据,执行一些重平均/操作,并更新成员变量spAvgData 在线程中,StockReader可以使用getspAvgData()方法访问StockAvgDataCollector实例及其成员spAvgData 因此线程A只执行读操作,线程B执行读/写操作

我有一个与java线程相关的问题

举一个非常简单的例子,假设我有两个线程

线程运行StockReader类实例

运行StockAvgDataCollector类实例的线程B

在线程B中,StockAvgDataCollector连续收集一些市场数据,执行一些重平均/操作,并更新成员变量spAvgData

在线程中,StockReader可以使用getspAvgData()方法访问StockAvgDataCollector实例及其成员spAvgData

因此线程A只执行读操作,线程B执行读/写操作

问题

  • 现在,在这个场景中,我需要同步、原子功能、锁定或任何与并发相关的东西吗?线程A是否读取旧值并不重要

  • 由于线程A只进行读取而不更新任何内容,并且只有线程B执行任何写入操作,因此会出现死锁情况吗

  • 我已经从下面的链接粘贴了一段。从那一段来看,似乎我确实需要担心某种类型的锁定/同步

    读写器锁定

    当使用线程从对象读取数据时,不一定需要阻止另一个线程同时读取数据。只要线程只读取而不更改数据,就没有理由不能并行读取。J2SE 5.0 java.util.concurrent.locks包提供了实现这种类型锁定的类。ReadWriteLock接口维护一对关联锁,一个用于只读,一个用于写入。readLock()可以由多个读线程同时持有,只要没有写入程序。writeLock()是独占的。从理论上讲,很明显,使用读写器锁来提高并发性比使用互斥锁可以提高性能。然而,这种性能改进只有在多处理器上才能完全实现,并且与被修改的数据相比,数据的读取频率以及读写操作的持续时间都是如此

    在我的示例中,哪个并发实用程序更便宜、更合适

    java.util.concurrent.atomic

    java.util.concurrent.locks

    java.util.concurrent.ConcurrentLinkedQueue?-在这种情况下,StockAvgDataCollector将添加,StockReader将删除。不会公开任何getspAvgData()方法

    谢谢 阿米特

  • 如果您不介意线程A可以读取完全无意义的数据(包括部分更新的数据),那么不,您不需要任何同步。不过,我想你应该介意
  • 如果您只使用一个互斥锁,或者
    ReentrantReadWriteLock
    ,并且在持有锁时不暂停或无超时睡眠,则不会出现死锁。如果您确实执行了不安全的线程操作,或者尝试推出您自己的同步解决方案,那么您将需要担心它
  • 如果您使用阻塞队列,那么您还需要在
    StockReader
    中持续运行摄取循环
    ReadWriteLock
    在单核处理器上仍然是有益的——无论线程是同时运行还是仅仅由上下文开关交错运行,问题都是一样的


    如果你至少不使用某种形式的同步(例如,
    volatile
    ),那么你的读者可能永远看不到任何变化。

    好吧,当你有多个读者和至少一个作者时,读写锁的整件事真的很有意义。。。因此,您可以保证生动性(如果没有其他线程正在编写,您就不会阻塞任何阅读器线程)。但是,您只有两个线程

    如果您不介意线程B读取spAvgData的旧(但未损坏)值,那么我会选择AtomicDouble(或AtomicReference,取决于spAvgData的数据类型)

    所以代码应该是这样的

    public class A extends Thread {
      // spAvgData
      private final AtomicDouble spAvgData = new AtomicDouble(someDefaultValue);
    
      public void run() {
        while (compute) {
         // do intensive work
         // ...
          // done with work, update spAvgData
         spAvgData.set(resultOfComputation);
        }
      }
    
      public double getSpAvgData() {
        return spAvgData.get();
      }
    }
    // --------------
    
    public class B {
      public void someMethod() {
        A a = new A();
        // after A being created, spAvgData contains a valid value (at least the default)
        a.start();
        while(read) {
          // loll around
          a.getSpAvgData();
        }
      }
    }
    

    是的,同步很重要,你需要考虑两个参数:SPAVGDATA变量的可见性和它的更新的原子性。为了保证线程A在线程B中对spAvgData变量的可见性,可以将该变量声明为

    volatile
    或作为一个变量。此外,您还需要使用同步和锁定来保护更新的操作是原子的,以防涉及更多不变量,或者更新操作是复合操作。如果只有线程B正在更新该变量,则不需要同步,并且可见性应足以让线程A读取该变量的最新值。

    很抱歉,我不知道。刚刚接受了我之前所有的问题。感谢您指出这一点。当然,Java规范保证对int(及更小)和引用的更新是原子的,因此易失性int或对象引用可以工作,后者提供了作者正在替换的对象。感谢大家的回答,我认为所有答案都是好的,值得同等接受。但是stackoverflow只允许接受一个答案。