Java:线程共享数据的框架

标签 java multithreading thread-safety

我已经编写了一些多线程的业余爱好程序和一些在我之前的(工程/物理)研究中,所以我认为自己在同步/线程安全和原语领域具有高于初学者的知识,什么是普通用户发现 JMM 和多线程等具有挑战性。

我发现我需要什么,但没有适当的方法将类的实例或静态成员标记为由不同线程共享。想一想,我们有访问规则,例如私有(private)/ protected /公共(public)以及关于如何命名 getters/setters 和很多东西的约定。

但是线程呢?如果我想将一个变量标记为线程共享并让它遵循某些规则怎么办? volatile /原子引用可能会完成这项工作,但有时您只需要使用互斥锁。当您必须手动记住使用某些东西时……您会忘记它 :) - 在某些时候。

于是灵机一动,原来我不是第一个,我也查了一下http://checkthread.org/example-threadsafe.html - 他们似乎有一个相当不错的代码分析器,我稍后可能会尝试使用它来让我做一些我想做的事情。

但是回到最初的问题。假设我们需要比消息传递框架低一点的东西,而我们需要比原始互斥体高一点的东西……我们有什么……呃……什么都没有?

基本上,我所做的是一种用于线程的纯 Java super 简单框架,它允许您将类成员声明为共享或非共享......有点像 :)。

下面是一个如何使用它的例子:

public class SimClient extends AbstractLooper {

    private static final int DEFAULT_HEARTBEAT_TIMEOUT_MILLIS = 2000;
    // Accessed by single threads only
    private final SocketAddress socketAddress;
    private final Parser parser;
    private final Callback cb;
    private final Heart heart;
    private boolean lookingForFirstMsg = true;
    private BufferedInputStream is;
    // May be accessed by several threads (T*)  
    private final Shared<AllThreadsVars> shared = new Shared<>(new AllThreadsVars());

.
.
.
.

    static class AllThreadsVars {

        public boolean connected = false;
        public Socket socket = new Socket();
        public BufferedOutputStream os = null;
        public long lastMessageAt = 0;
    }

要访问标记为线程共享的变量,您必须向共享对象发送类似可运行的仿函数:

public final void transmit(final byte[] data) {
    shared.run(new SharedRunnable<AllThreadsVars, Object, Object>() {

        @Override
        public Object run(final AllThreadsVars sharedVariable, final Object input) {
            try {
                if (sharedVariable.socket.isConnected() && sharedVariable.os != null) {
                    sharedVariable.os.write(data);
                    sharedVariable.os.flush();
                }
            } catch (final Exception e) { // Disconnected
                setLastMessageAt(0);
            }
            return null;
        }
    }, null);
}

共享可运行对象的定义如下:

public interface SharedRunnable<SHARED_TYPE, INPUT, OUTPUT> {
    OUTPUT run(final SHARED_TYPE s, final INPUT input);
}

这是要去哪里? 好吧,这给了我帮助(是的,你可以泄漏并破坏它,但不太可能)我可以将变量集(不仅仅是变量)标记为线程共享,一旦完成,就可以在编译时保证它(我不能忘记同步一些方法)。它还允许我在编译时标准化和执行测试以查找可能的死锁(虽然 atm 我只在运行时实现它因为在编译时使用上述框架进行它可能需要的不仅仅是 java 编译器)。

基本上这对我来说非常有用,我想知道我是否只是在这里重新发明轮子,或者这可能是我不知道的一些反模式。我真的不知道该问谁。 (哦,是的,Shared.run(SharedRunnable r,INPUT 输入)就像

private final <OUTPUT, INPUT> OUTPUT run(final SharedRunnable<SHARED_TYPE, INPUT, OUTPUT> r, final INPUT input) { 
    try {
        lock.lock();
        return r.run(sharedVariable, input);
    } finally {
        lock.unlock();
    }
}

这只是我自己的实验,所以它还没有真正完成,但我现在有一个不错的项目正在使用它,它确实帮了很多忙。

最佳答案

你的意思是像this ? (可以通过 findbugs 等工具强制执行。)

关于Java:线程共享数据的框架,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7179793/

相关文章:

java - Swing JFormattedTextField 纠正多行粘贴

go - 正在将标准库日志重定向到 logrus 线程安全

java - Android 中的 java.util.Observable 是线程安全的吗?

java - TextureView.getBitmap() 函数是否有任何快速替代方案?

Java:如果抽象类Foo返回Object,具体类Bar可以返回String或Integer吗?

java - Thread.interrupted()清除线程中断状态的原因是什么?

javascript - Node.js 中的并行 SQLite 查询

multithreading - Scala中的后台任务

java - ConcurrentHashMap 的计算、computeIfAbsent 和computeIfPresent 方法是完全原子的吗?

java - Display.getDefault.syncExec() 在 headless 模式下无法正确运行