Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/223.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 如何锁定threadA写入和threadB读取的两个变量(Android)_Java_Android_Multithreading_Locking - Fatal编程技术网

Java 如何锁定threadA写入和threadB读取的两个变量(Android)

Java 如何锁定threadA写入和threadB读取的两个变量(Android),java,android,multithreading,locking,Java,Android,Multithreading,Locking,我正在开发一个Android应用程序,它使用两个线程,第一个(writer)线程正在更新两个变量,第二个(reader)线程在计算中同时使用这两个变量 如何确保第二个线程接收到正确的值? 这是我的第一个java锁定问题。我一直在读有关同步、易变、trylock的文章,但仍然不清楚。对于一个变量来说,这很容易,但不知道如何对两个变量做到这一点 详细信息: 变量位于共享公共类AppState extends应用程序中: public long appstate.writerVar1; public

我正在开发一个Android应用程序,它使用两个线程,第一个(writer)线程正在更新两个变量,第二个(reader)线程在计算中同时使用这两个变量
如何确保第二个线程接收到正确的值?
这是我的第一个java锁定问题。我一直在读有关同步、易变、trylock的文章,但仍然不清楚。对于一个变量来说,这很容易,但不知道如何对两个变量做到这一点

详细信息:
变量位于共享公共类AppState extends应用程序中:

public long appstate.writerVar1;
public int appstate.writerVar2;
在主活动中,将创建线程,并将appstate传递给线程:

writerThread.appstate = appstate;
...
readerThread.appstate = appstate;
然后,writerThread和readerThread都可以访问变量,如下所示:

writerThread,示例:

appstate.writerVar1 = 1234;
appstate.writerVar2 = 5678;
readerThread,示例:

if( (appstate.writerVar1 == 9) && (appstate.writerVar2 == 6) ){
它应该是这样工作的:

writerThread:
-锁定两个变量
-用新值更新这两个值
-解锁

readerThread:
-锁定两个变量
-读取值
-解锁

有人能给我看一下java代码吗?谢谢

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

谢谢很抱歉延迟回答,但请阅读更多关于此的信息,包括关于可变对象的信息。
我试图理解如何从主活动中创建的writerThread和readerThread调用它,并得出以下代码:

writerThread:

私人编写器状态wsW

var1W=123
var2W=456
wsW=新的WriterState(var1W,var2W)
appstate.setWriterState(wsW)

readerThread:


私有WriterState wsR

wsR=appstate.getWriterState()
var1R=wsR.getVar1()
var2R=wsR.getVar2()

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

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

我在这里也看到了一个例子。
它们将计数器对象传递给两个线程。这种情况下不可能出现这种情况吗?

同步
和编程使用
java.util.concurrent.Lock
都可以,但我更喜欢第二种。假设读取器线程只需要对值进行简单检查,下面是一个解决方案:

编辑:这样读卡器线程就不会读取变量。相反,读者感兴趣的检查是在
AppState
类中完成的。显然,只有当您只需要检查两个变量的一件事情,并且事先知道它时,这才有效

public class AppState
{
    private long writerVar1;
    private int writerVar2;

    private ReentrantLock lock = new ReentrantLock();

    public void setValues(long longValue, int intValue)
    {
        lock.lock();
        try
        {
            writerVar1 = longValue;
            writerVar2 = intValue;
        }
        finally
        {
            lock.unlock();
        }
    }

    public boolean isValuesCorrect()
    {
        lock.lock();
        try
        {
            return (writerVar1 == 9) && (writerVar2 == 6);
        }
        finally
        {
            lock.unlock();
        }
    }
//rest of the class body goes here
}

请注意,这两个值必须
私有
,并且只能通过使用相同锁的方法访问,否则您实际上没有线程安全访问。

同步
和编程使用
java.util.concurrent.lock
都可以,但我更喜欢第二个。假设读取器线程只需要对值进行简单检查,下面是一个解决方案:

编辑:这样读卡器线程就不会读取变量。相反,读者感兴趣的检查是在
AppState
类中完成的。显然,只有当您只需要检查两个变量的一件事情,并且事先知道它时,这才有效

public class AppState
{
    private long writerVar1;
    private int writerVar2;

    private ReentrantLock lock = new ReentrantLock();

    public void setValues(long longValue, int intValue)
    {
        lock.lock();
        try
        {
            writerVar1 = longValue;
            writerVar2 = intValue;
        }
        finally
        {
            lock.unlock();
        }
    }

    public boolean isValuesCorrect()
    {
        lock.lock();
        try
        {
            return (writerVar1 == 9) && (writerVar2 == 6);
        }
        finally
        {
            lock.unlock();
        }
    }
//rest of the class body goes here
}

请注意,这两个值都必须是私有的,并且只能通过使用相同锁的方法访问,否则您就没有真正的线程安全访问。

OO设计的关键是封装。在处理多线程时,它变得更加重要。如果这两个变量构成必须一致更新和读取的共享状态,那么

  • 此共享状态不应为公共状态,因为它强制此状态的每个客户端遵守与其他客户端的协作协议
  • 此共享状态应封装在对象中,该对象控制对状态的访问
因此,AppState对象的字段应该是私有的。这条规则在99%的情况下都是正确的。公共领域是一个大禁忌

然后所有对字段的访问都应该同步(读和写)。由于这两个字段构成了一条连贯的信息,所以应该将它们放在一个类中(我们称之为WriterState)。如果这个类是可变的,那么每次调用getState()和setState()时,您都必须通过共享状态创建一个helf的副本,因此使用不可变类更容易、更快,它可以由多个线程共享,而无需同步

/**
 * 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());
    }
}

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

  • 此共享状态不应为公共状态,因为它强制此状态的每个客户端遵守与其他客户端的协作协议
  • 此共享状态应封装在对象中,该对象控制对状态的访问
因此,AppState对象的字段应该是私有的。这条规则在99%的情况下都是正确的。公共领域是一个大禁忌

然后所有对字段的访问都应该同步(读和写)。由于这两个字段构成了一条连贯的信息,所以应该将它们放在一个类中(我们称之为WriterState)。如果这个类是可变的,那么每次getState()和se