为什么同步不起作用

时间:2014-06-24 12:12:33

标签: java multithreading synchronization

这里的问题是同步不起作用。我的另一个线程甚至在我的第一个线程在synchronized块中完成执行之前就被执行了。当我传递“someClass.class”时,它工作正常。也许我的说法不对,或者我的程序有些错误。

主:

public class Main {
    public static void main(String[] args) {
        SharedObject object = new SharedObject();
        ClassA t1 = new ClassA("Thread 1", object);
        ClassA t2 = new ClassA("Thread 2", object);
        t1.start();
        t2.start();
    }

}

共享对象:

class SharedObject {
    volatile int value = 10;
}

ClassA的:

class ClassA extends Thread{
    SharedObject object;
    int data;

    public ClassA(String name, SharedObject object) {
        super(name);
        this.object = object;
    }

    @Override
    public void run() {     
        name();
    }

    public void name() {
        synchronized (this) {
            if(getName().equals("Thread 1")){
                System.out.println("Before modifying "+getName()+" value = "+object.value);
                object.value = 100;
                System.out.println("After modifying "+getName()+" value = "+object.value);
                data = object.value;
            }else{
                System.out.println("Before modifying "+getName()+" value = "+object.value);
                object.value = 200;
                System.out.println("After modifying "+getName()+" value = "+object.value);
                data = object.value;
            }
        }

    }
}

计划的输出:

Before modifying Thread 2 value = 10
Before modifying Thread 1 value = 10
After modifying Thread 2 value = 200
After modifying Thread 1 value = 100

请帮助我理解这一点。

4 个答案:

答案 0 :(得分:5)

您正在同步#34;此",但已创建了2个不同的ClassA实例。因此,同步发生在不同的对象上。

答案 1 :(得分:3)

虽然大多数答案都是正确的,但是我可以为您可以进行的不同类型的同步添加更多解释。

同步方法

例如:

public synchronized void name() {

        if(getName().equals("Thread 1")){
            System.out.println("Before modifying "+getName()+" value = "+object.value);
            object.value = 100;
            System.out.println("After modifying "+getName()+" value = "+object.value);
            data = object.value;
        }else{
            System.out.println("Before modifying "+getName()+" value = "+object.value);
            object.value = 200;
            System.out.println("After modifying "+getName()+" value = "+object.value);
            data = object.value;
        }
}

这可以确保只有一个线程会在某个特定实例的某个时间点执行此特定方法。任何其他线程将在方法起点等待。

同步实例

例如:

public void name() {

    synchronized (this) {
        if(getName().equals("Thread 1")){
            System.out.println("Before modifying "+getName()+" value = "+object.value);
            object.value = 100;
            System.out.println("After modifying "+getName()+" value = "+object.value);
            data = object.value;
        }else{
            System.out.println("Before modifying "+getName()+" value = "+object.value);
            object.value = 200;
            System.out.println("After modifying "+getName()+" value = "+object.value);
            data = object.value;
        }
    }

}

这可确保只有一个主题会在某个特定实例的某个时间点执行此特定块。任何其他线程都会在块的开头等待。

当synchronized块包含整个方法时,这相当于synchronized方法。

同步类

public void name() {

    synchronized (ClassA.class) {
        if(getName().equals("Thread 1")){
            System.out.println("Before modifying "+getName()+" value = "+object.value);
            object.value = 100;
            System.out.println("After modifying "+getName()+" value = "+object.value);
            data = object.value;
        }else{
            System.out.println("Before modifying "+getName()+" value = "+object.value);
            object.value = 200;
            System.out.println("After modifying "+getName()+" value = "+object.value);
            data = object.value;
        }
    }

}

这确保只有一个主题会在某个时间点为该类的任何实例执行此特定块。任何其他线程将在块的开头等待。这可以解决您的问题。

同步互斥锁

虽然上述所有方法都使用隐式互斥锁,但同步线程的一种好方法是使用自己的互斥锁。如果深入了解并发实现,这可以提高整体可扩展性。

例如:

private staic final Object mutex = new Object();

public void name() {

    synchronized (mutex) {
        if(getName().equals("Thread 1")){
            System.out.println("Before modifying "+getName()+" value = "+object.value);
            object.value = 100;
            System.out.println("After modifying "+getName()+" value = "+object.value);
            data = object.value;
        }else{
            System.out.println("Before modifying "+getName()+" value = "+object.value);
            object.value = 200;
            System.out.println("After modifying "+getName()+" value = "+object.value);
            data = object.value;
        }
    }

}

答案 2 :(得分:2)

您需要在object而非this上同步。

thist1t2不同,因为它们是同一个类的两个不同实例,因此是并发执行。

答案 3 :(得分:1)

在共享对象上同步(由名为object的变量引用)不在Thread实例上(由this引用)。