简体   繁体   English

一个线程更新变量,另一个读取它,我是否需要特殊的东西

[英]One thread updates variable and another read it, do I need something special

I have a class that has the object "Card". 我有一个对象为“卡”的类。 This class keeps checking to see if the object is not null anymore. 此类不断检查对象是否不再为null。 Only one other thread can update this object. 只有另一个线程可以更新此对象。 Should I just do it like the code below? 我应该像下面的代码那样做吗? Use volatile?Syncronized? 使用volatile吗? lock (which I dont know how to use really)? 锁(我不知道该怎么用)? What do you recommend as easiest solution? 您推荐什么是最简单的解决方案?

Class A{

 public Card myCard = null;


 public void keepCheck(){

    while(myCard == null){
       Thread.sleep(100)
    }
    //value updated
     callAnotherMethod();
 }

Another thread has following: 另一个线程具有以下内容:

public void run(){
     a.myCard = new Card(5);
 }

What do you suggest? 你有什么建议?

如果要轮询从另一个线程进行修改,则该变量需要是可变的,但是更好的解决方案是使用wait() / notify()Semaphore来使其他线程保持睡眠状态,直到初始化myCard变量为止。

Looks like you have a classic producer/consumer case. 看起来您有一个经典的生产者/消费者案例。

You can handle this case using wait()/notify() methods. 您可以使用wait()/ notify()方法处理这种情况。 See here for an example: How to use wait and notify in Java? 请参见此处的示例: 如何在Java中使用等待和通知?

Or here, for more examples: http://www.programcreek.com/2009/02/notify-and-wait-example/ 或在此处查看更多示例: http : //www.programcreek.com/2009/02/notify-and-wait-example/

You should use a proper wait event (see the Guarded Block tutorial), otherwise you run the risk of the "watching" thread seeing the reference before it sees completely initialized member fields of the Card . 您应该使用适当的等待事件(请参阅Guarded Block教程),否则冒着“监视”线程在看到Card完全初始化的成员字段之前看到引用的风险。 Also wait() will allow the thread to sleep instead of sucking up CPU in a tight while loop. 另外, wait()将允许线程进入睡眠状态,而不是在紧的while循环中占用CPU资源。

For example: 例如:

Class A {

    private final Object cardMonitor = new Object();
    private volatile Card myCard;

    public void keepCheck () {
        synchronized (cardMonitor) {
            while (myCard == null) {
                try {
                    cardMonitor.wait();
                } catch (InterruptedException x) {
                    // either abort or ignore, your choice
                }
            }
        }
        callAnotherMethod();
    }

    public void run () {
        synchronized (cardMonitor) {
            myCard = new Card(5);
            cardMonitor.notifyAll();
        }
    }

}

I made myCard private in the above example. 在上面的示例中,我将myCard私有。 I do recommend avoiding lots of public fields in a case like this, as the code could end up getting messy fast. 我确实建议在这种情况下避免使用大量公共字段,因为代码最终可能很快变得混乱。

Also note that you do not need cardMonitor -- you could use the A itself, but having a separate monitor object lets you have finer control over synchronization. 还要注意,您不需要 cardMonitor您可以使用A本身,但是拥有一个单独的监视器对象可以使您更好地控制同步。

Beware, with the above implementation, if run() is called while callAnotherMethod() is executing, it will change myCard which may break callAnotherMethod() (which you do not show). 当心,通过上述实现,如果run()执行callAnotherMethod()调用callAnotherMethod() ,它将更改myCard ,这可能会破坏callAnotherMethod() (您未显示)。 Moving callAnotherMethod() inside the synchronized block is one possible solution, but you have to decide what the appropriate strategy is there given your requirements. callAnotherMethod()移到同步块内是一种可能的解决方案,但是您必须根据需要确定合适的策略。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM