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 如何在AKKA演员中实现线程安全?_Java_Multithreading_Concurrency_Thread Safety_Akka - Fatal编程技术网

Java 如何在AKKA演员中实现线程安全?

Java 如何在AKKA演员中实现线程安全?,java,multithreading,concurrency,thread-safety,akka,Java,Multithreading,Concurrency,Thread Safety,Akka,我的项目需要大量的异步编程,所以我选择AKKA平台,就像actor模型一样,可以实现异步系统,就像编写同步代码一样,而不必担心线程问题。在我遇到以下问题(演示代码)之前,一切正常: 首先发送一条“锁定”消息,然后发送一条“解锁”消息,在尝试在收到发送消息时解锁时,抛出了一个IllegalMonitorStateException,我发现这是由于不同的线程实际处理不同的消息,s->lock.lock()和s->lock.unlock()在不同的线程中执行,因此会抛出IllegalMonitorSt

我的项目需要大量的异步编程,所以我选择AKKA平台,就像actor模型一样,可以实现异步系统,就像编写同步代码一样,而不必担心线程问题。在我遇到以下问题(演示代码)之前,一切正常:

首先发送一条“锁定”消息,然后发送一条“解锁”消息,在尝试在收到发送消息时解锁时,抛出了一个
IllegalMonitorStateException
,我发现这是由于不同的线程实际处理不同的消息,
s->lock.lock()
s->lock.unlock()
在不同的线程中执行,因此会抛出
IllegalMonitorStateException

我之前的假设是,参与者的所有操作都在一个线程中执行,因此它是完全线程安全的,不必担心线程问题。当我在我的项目中广泛使用AKKA时,现在我非常担心和不清楚何时需要使用AkkA考虑线程问题。例如,在以下演示代码中:

import akka.actor.AbstractActor;
import akka.japi.pf.ReceiveBuilder;
import java.util.concurrent.locks.ReentrantLock;

public class TestActor extends AbstractActor {
    private final ReentrantLock lock  = new ReentrantLock();

    @Override
    public Receive createReceive() {
        return ReceiveBuilder.create()
                .matchEquals("lock", s -> lock.lock())
                .matchEquals("unlock", s -> lock.unlock())
                .build();
    }
}
public class TestActor1 extends AbstractActor {
    private int count  = 0;
    private Map<Integer, Integer> map = new HashMap<>();
    
    @Override
    public Receive createReceive() {
        return ReceiveBuilder.create()
                .matchEquals("action1", s -> count++)
                .matchEquals("action2", s -> getSender().tell(count, getSelf()))
                .matchEquals("action3", s -> map.put(3, 2))
                .matchEquals("action4", s -> getSender().tell(map.get(3), getSelf()))
                .build();
    }
}

Akka的设计是线程安全的。而且,在一个参与者中永远不需要锁定或同步。不应该这样做

Akka通过一次处理一条消息来实现线程安全。参与者不能同时处理多条消息。但是消息可能会也将在不同的线程中处理。(这是默认行为,但可以使用pin分配器进行更改)

不需要诸如synchronized或AtomicInteger之类的并发保护 因为actor实例一次处理一条消息

关于最后的问题

计数和映射的使用方式是线程安全的吗

是的,它是线程安全的

我是否需要使用volatile进行计数并使用ConcurrentHashMap进行映射

不,没有必要这么做。看

用外行的话来说,这意味着 当参与者处理下一条消息时,参与者是可见的。所以 actor中的字段不必是可变的或等效的


Akka的设计是线程安全的。而且,在一个参与者中永远不需要锁定或同步。不应该这样做

Akka通过一次处理一条消息来实现线程安全。参与者不能同时处理多条消息。但是消息可能会也将在不同的线程中处理。(这是默认行为,但可以使用pin分配器进行更改)

不需要诸如synchronized或AtomicInteger之类的并发保护 因为actor实例一次处理一条消息

关于最后的问题

计数和映射的使用方式是线程安全的吗

是的,它是线程安全的

我是否需要使用volatile进行计数并使用ConcurrentHashMap进行映射

不,没有必要这么做。看

用外行的话来说,这意味着 当参与者处理下一条消息时,参与者是可见的。所以 actor中的字段不必是可变的或等效的


你可能想用
action3
action4
代替
action2
@IvanStanislavciuc是的,这些都是打字错误,谢谢你的指点。我还编辑了这个问题,添加了更多的信息来说明为什么我需要Actor中的锁。这似乎是一个问题。关于你的编辑,依我看,你不应该这样做。Akka设计为无锁。如果你想利用背压,考虑使用Akka流代替。它可以与参与者集成,因此您的处理仍然可以在参与者中进行。但是您应该创建一个新问题,而不必修改此问题,以避免对此问题进行重大更改。您可能是想使用
action3
action4
而不是
action2
@IvanStanislavciuc是的,这些都是打字错误,谢谢您的提醒。我还编辑了这个问题,添加了更多的信息来说明为什么我需要Actor中的锁。这似乎是一个问题。关于你的编辑,依我看,你不应该这样做。Akka设计为无锁。如果你想利用背压,考虑使用Akka流代替。它可以与参与者集成,因此您的处理仍然可以在参与者中进行。但是您应该创建一个新问题,而不必修改此问题,以避免对该问题进行重大更改。
public class PipeLineActor extends AbstractActor {
    private final ReentrantLock stallLock = new ReentrantLock();

    private Thread executionLoop = new Thread(() -> {
        while (true){
            stallLock.lock();
            stallLock.unlock();
            
            // issue tasks to down stream actors
        }
    });

    @Override
    public Receive createReceive() {
        return ReceiveBuilder.create()
                // down stream actor send "backPressureHi" when back pressure is high to stall the executionLoop
                .matchEquals("backPressureHi", s -> stallLock.lock())
                // down stream actor send "backPressureNormal" when back pressure resumed normal to resume the executionLoop
                .matchEquals("backPressureNormal", s -> stallLock.unlock())
                .build();
    }
}