混淆关于相同/不同对象上的java线程

时间:2014-08-23 05:36:42

标签: java multithreading

public class Computation extends Thread {

    private int num;
    private boolean isComplete;

    public Computation(int nu) {
        num = nu;
    }

    public void run() {
        System.out.println("Thread Called is: " + Thread.currentThread().getName());
    }

    public static void main(String... args) {
        Computation [] c = new Computation[4];
        for (int i = 0; i < 3; i++) {
            c[i] = new Computation(i);
            c[i].start();
        }
    }
}

我的问题是在每次创建线程的新Computation对象时创建的main函数,以及为什么我们需要snhernoized run方法?正如我们所知道的,每个不同的类对象'this'引用是不同的,所以我们不需要同步。

另外在另一个例子中:

public class DiffObjSynchronized implements Runnable {

    @Override
    public void run() {
        move(Thread.currentThread().getId());           
    }

    public synchronized void move(long id) {
        System.out.print(id + " ");
        System.out.print(id + " ");
    }

    public static void main(String []args) {
        DiffObjSynchronized a = new DiffObjSynchronized();
        /**** output ****/
        // 8    9   8   9
        new Thread(a).start();
        new Thread(new DiffObjSynchronized()).start();
    }
}

这是第二个例子,就像我们首先在2个不同的类实例上创建一个Thread一样。这里我们同步move()方法但是按照定义: “两个不同的对象可以同时进入同步方法”

请分享您的反馈意见?

3 个答案:

答案 0 :(得分:1)

由于您为每个线程创建了一个新实例,因此您的线程在不同的对象上运行。 synchronized使用的内部锁属于实例。因此,线程输入的同步方法由不同的锁保护。

答案 1 :(得分:1)

如果我理解正确,您的问题是:“为什么move方法同步?”

答案是:它不应该是,原因有两个:

  1. 它不会访问任何字段,因此一旦在该方法中包含许多线程,就不会有任何损坏。

  2. 每个线程获取对象的不同实例,因此获得不同的锁。所以synchronized修饰符没有区别。每个线程仍然可以输入自己的实例的move方法,因为它们具有单独的锁。

  3. 只有在线程之间共享某些数据并且至少有一个线程正在修改该数据时,才需要进行同步。

答案 2 :(得分:0)

您需要了解同步的工作原理。 当线程进入同步块时,线程会对正在同步的对象进行“锁定”。如果您有一个synchronized方法,那么在这种情况下,该对象将成为'this'实例。现在,没有2个线程可以同时锁定同一个对象。对象锁是基于哲学的互斥锁,所以只有一次线程可以一次持有互斥锁。当持有锁的线程退出synchronized方法或块时,它会释放互斥锁,因此对象锁可供其他线程请求锁定。

This链接可以很好地解释这些概念。它有关于反汇编字节代码的图片,它显示了线程如何获取和保留锁定以及为什么2个不同对象上的2个线程不会相互阻塞。