Java同步和线程

时间:2009-07-16 05:15:41

标签: java multithreading synchronized

我遇到的问题是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"

我不希望他们混在一起。

3 个答案:

答案 0 :(得分:1)

您只是分别同步getValuesetValue的访问权限而不是双线

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

然后当然两个线程可以在一个setValuegetValue

之间交错

答案 1 :(得分:1)

接下来会发生什么:

  1. 线程1设置值
  2. 线程2设置值
  3. 线程1读取线程2设置的值。
  4. 为了解决这个问题,你需要有一个锁定对象来保护两个线程的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 :(得分:0)

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

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