java - 如何锁定threadS写入线程读取的两个变量(Android)

标签 java android multithreading locking

我正在开发一个使用两个线程的 Android 应用程序,第一个(编写器)线程正在更新两个变量,第二个(读取器)线程在计算中同时使用这两个线程。
如何确保第二个线程接收到正确的值?
这是我的第一个 java 锁定问题。我一直在阅读有关 synchronized、volatile、trylock 的内容,但仍然不清楚。对于一个变量,这很“简单”,但不明白如何对两个变量执行此操作。

详情:
变量位于共享公共(public)类 AppState extends Application 中:

public long appstate.writerVar1;
public int appstate.writerVar2;

在主 Activity 中创建线程并将应用程序状态传递给线程:

writerThread.appstate = appstate;
...
readerThread.appstate = appstate;

然后变量可以被 writerThread 和 readerThread 访问,如下所示:

writerThread,例子:

appstate.writerVar1 = 1234;
appstate.writerVar2 = 5678;

readerThread,例子:

if( (appstate.writerVar1 == 9) && (appstate.writerVar2 == 6) ){

它应该像这样工作:

作者线程:
- 锁定两个变量
- 用新值更新两者
- 解锁

读者线程:
- 锁定两个变量
- 读取值
- 解锁

有人可以告诉我执行此操作的 Java 代码吗?谢谢!

--- 添加于 2012 年 4 月 23 日 ---

谢谢。很抱歉延迟回答,但请阅读更多相关信息,包括可变对象 http://www.javaranch.com/journal/2003/04/immutable.htm
我试图了解如何从主 Activity 中创建的 writerThread 和 readerThread 调用它,并想出了这段代码:

作者线程:

私有(private) WriterState wsW;
...
var1W = 123;
var2W = 456;
wsW = new WriterState(var1W, var2W);
appstate.setWriterState(wsW);

读者线程:


私有(private) WriterState wsR;
...
wsR = appstate.getWriterState();
var1R = wsR.getVar1();
var2R = wsR.getVar2();

我试过这段代码,它似乎运行正常。我可以在读取 var1R 和 var2R 之间添加一个新的 var1W 和 var2W。

现在我的下一个问题:
a) 这个代码可以吗?
b) 假设 setWriterState 代码在一个循环中,这不会吃掉所有内存吗?
c) WriterState 类怎么可能是可变的,我相信这里不可能是这种情况(你说:如果 WriterState 类是可变的)

我在这里也看到了一个例子 http://tutorials.jenkov.com/java-concurrency/synchronized.html 。 他们将 Counter 对象传递给两个线程。对于这种情况,这样的事情是不可能的吗?

最佳答案

面向对象设计的关键是封装。而在处理多线程时,它就变得更加重要。如果这两个变量构成必须连贯更新和读取的共享状态,则

  • 这个共享状态不应该是公开的,因为它强制这个状态的每个客户端遵守与其他客户端的协作协议(protocol)
  • 这个共享状态应该封装在一个对象中,该对象控制对状态的访问

因此,AppState 对象的字段应该是私有(private)的。这个规则在 99% 的情况下都是正确的。公共(public)领域是一个很大的禁忌。

然后所有对字段的访问都应该同步(读取和写入)。由于这两个字段构成一条连贯的信息,您应该将它们放在一个类中(我们称之为 WriterState)。如果这个类是可变的,你必须在每次调用 getState() 和 setState() 时通过共享状态复制一份,所以使用不可变类更容易和更快,它可以被多个共享没有同步的线程。

/**
 * Immutable class: final, contains only final fields wich are themselves immutable.
 */
public final class WriterState {
    private final long var1;
    private final int var2;

    public WriterState(long var1, int var2) {
        this.var1 = var1;
        this.var2 = var2;
    }

    public long getVar1() {
        return this.var1;
    }

    public int getVar2() {
        return this.var2;
    }
}

public class AppState {
    private WriterState writerState;

    public synchronized void setWriterState(WriterState ws) {
        this.writerState = ws;
    }

    public synchronized WriterState getWriterState() {
        return this.writerState;
    }
}

如果 WriterState 类是可变的,那么您应该执行以下操作以使其成为线程安全的:

public class AppState {
    private WriterState writerState;

    public synchronized void setWriterState(WriterState ws) {
        this.writerStatenew WriterState(ws.getVar1(), ws.getVar2());
    }

    public synchronized WriterState getWriterState() {
        return new WriterState(this.writerState.getVar1(), this.writerState.getVar2());
    }
}

关于java - 如何锁定threadS写入线程读取的两个变量(Android),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10261131/

相关文章:

android - 所有异步任务完成后如何做某事?

c++ - 将程序拆分为 4 个线程比单个线程慢

java - 可以使用命名变量在 groovy 的闭包中打印命名组吗?

java - 通过id获取组件的值?

android - 备份我的整个应用程序(sqlite、文件夹和文件)的最佳方式 - Android

java - onCreate 中 getWidth() 返回 0

java - 试图阻止Java中同时运行的单个线程

ruby - 生产者/消费者的特例

java - pretty-print XML 文件

java - JDBC/Hibernate 获取大小和内存问题