【问题标题】:Java Synchronized and ThreadsJava 同步和线程
【发布时间】:2009-07-16 05:15:40
【问题描述】:

我遇到了 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 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", "lame" );
            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();
    }
}

偶尔我会收到"In Libya Thread congo cool" 这不应该发生。我只希望:
"In Libya Thread libya awesome"
"In Congo Thread congo cool"

我不希望它们混在一起。

【问题讨论】:

  • 你怎么能期待“在利比亚线程利比亚真棒”?您的程序不包含“真棒”一词

标签: java multithreading synchronized


【解决方案1】:

接下来会发生什么:

  1. 线程 1 设置值
  2. 线程 2 设置值
  3. 线程 1 读取线程 2 设置的值。

为了解决这个问题,您需要有 1 个锁对象来保护两个线程的 get/set 函数调用。最好的方法是创建一个额外的同步方法,它同时执行 set 和 get。然而,有时这是不可取的。在这种情况下,给两个线程一个锁对象。这只是一个普通的对象。然后他们在同步块中使用它。

每个线程的实现都会像下面这样,注意它们需要有完全相同的对象!

Object lockObject = new Object();
Thread t1 = new CongroThread(v, lockObject);
Thread t2 = new LibyaThread(v, lockObject);

...

class CongoThread implements Runnable {
    private ThreadValue v;
    private Object lockObject;

    public CongoThread(ThreadValue v, Object lockObject) {
    this.v = v;
    this.lockObject = lockObject,
    }
    public void run() {
        for (int i = 0; i < 10; i++) {
            synchronized(lockObject)
            {
                v.setValue( "congo", "lame" );
                v.getValue();
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    您只是分别同步访问getValuesetValue 而不是两行

    v.setValue( "congo", ..);
    v.getValue();
    

    那么当然这两个线程可能会在一个setValuegetValue之间交错

    【讨论】:

      【解决方案3】:

      您是否同步了 System.out.print 调用?如果没有同步,它们是线程安全的,但可能不会以正确的顺序发出。

      synchronzied(System.out) {
          System.out.print(....);
          System.out.flush();
      }
      

      【讨论】:

        猜你喜欢
        • 2011-07-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-16
        • 1970-01-01
        • 1970-01-01
        • 2011-01-17
        相关资源
        最近更新 更多