【问题标题】:java synchronized issuejava同步问题
【发布时间】:2009-07-16 05:39:17
【问题描述】:

我遇到了 Synchronized 不符合我预期的问题,我也尝试使用 volatile 关键字:

共享对象:


public class ThreadValue {
private String caller;
private String value;
public ThreadValue( String caller, String value ) {
    this.value = value;
    this.caller = caller;
}

public synchronized String getValue() {
    return this.caller + "     "  + this.value;
}
public synchronized void setValue( String caller, String value ) {
    this.caller = caller;
    this.value = value;
}
}

线程 1:


class CongoThread implements Runnable {
    private ThreadValue v;
    public CongoThread(ThreadValue v) {
    this.v = v;

    }
    public void run() {
    for (int i = 0; i  10; i++) {
    v.setValue( "congo", "cool" );
    v.getValue();
    }
    }
}

线程 2:


class LibyaThread implements Runnable {
    private ThreadValue v;
    public LibyaThread(ThreadValue v) {
    this.v = v;

    }
    public void run() {
    for (int i = 0; i  10; i++) {
       v.setValue( "libya", "awesome" );
       System.out.println("In Libya Thread " + v.getValue() );

    }
    }
}

调用类:


class TwoThreadsTest {
    public static void main (String args[]) {

    ThreadValue v = new ThreadValue("", "");
        Thread congo = new Thread( new CongoThread( v ) );
        Thread libya = new Thread( new LibyaThread( v ) );

    libya.start();
        congo.start();

    }
}

偶尔我会得到“在利比亚线程刚果很酷” 这不应该发生。我只期望: “在利比亚线程利比亚真棒” “在刚果线程刚果酷”

我不希望它们混在一起。

【问题讨论】:

    标签: java multithreading volatile synchronized


    【解决方案1】:

    调用可以像下面这样交错:

    Thread 1 : v.setValue()
    Thread 2 : v.setValue()
    Thread 1 : v.getValue() // thread 1 sees thread 2's value
    Thread 2 : v.getValue() // thread 2 sees thread 2's value
    

    【讨论】:

      【解决方案2】:

      这应该会得到你正在寻找的行为。

      线程 1:

      class CongoThread implements Runnable {
          private ThreadValue v;
      
          public CongoThread(ThreadValue v) {
              this.v = v;
          }
      
          public void run() {
              for (int i = 0; i < 10; i++) {
                  synchronized(v) {
                      v.setValue( "congo", "cool" );
                      System.out.println("In Congo Thread " + v.getValue() );
                  }
              }
          }
      }
      

      线程 2:

      class LibyaThread implements Runnable {
          private ThreadValue v;
      
          public LibyaThread(ThreadValue v) {
              this.v = v;
          }
      
          public void run() {
              for (int i = 0; i < 10; i++) {
                  synchronized(v) {
                      v.setValue( "libya", "awesome" );
                      System.out.println("In Libya Thread " + v.getValue() );
                  }
              }
          }
      }
      

      【讨论】:

      • 在一个重要的程序中,您可能甚至想隐藏这个级别的同步。拥有自己同步的 setValueAndReturnString() 之类的方法。您不想依赖调用者正确处理多线程。
      • 同意。我只是在想,通过向 Mo 提供应该实现他所寻求的行为的代码版本,以及其他人提供的响应,这将有助于他了解问题所在,并更好地了解同步的工作原理。跨度>
      【解决方案3】:

      对 getValue() 和 setValue() 的调用可能是交错的。

      也就是说,没有线程会在 getValue() 中同时另一个线程在 getValue() 或 setValue() 中,同样没有线程将在 setValue() 中,而另一个线程在 getValue() 或 setValue() 中)。

      但是,不能保证单个线程会连续调用 setValue() getValue() 而不会被另一个线程抢占。

      基本上,这是完全合法且可能的:

      线程 1:v.setValue()
      其他一些线程:任意数量的 v.getValue()'s/v.setValue()'s
      线程一:v.getValue()

      【讨论】:

        【解决方案4】:

        可能是这个顺序,所以它是正确的:

         v.setValue( "libya", "awesome" );
         //context switch
         v.setValue( "congo", "cool" );
         //context switch
         System.out.println("In Libya Thread " + v.getValue() );
        

        因此,您确实有某种意义上的竞争条件。每当您尝试调用同步方法时,同步都会获取锁,因此您需要另一种方式来暗示对变量的同步访问。例如,您可以从方法中删除同步并执行以下操作:

        public void run() 
        {
          for (int i = 0; i  10; i++) 
          {
           synchronized(v)
           {
              v.setValue( "caller", "value" );
              v.getValue();
           }
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-12
          • 1970-01-01
          相关资源
          最近更新 更多